Using COLLATE in Android SQLite - Locales is ignored in LIKE statement

前端 未结 5 1123
梦谈多话
梦谈多话 2020-11-30 14:59

When creating my SQLite database in Android I set the database locale - db.setLocale(new Locale(\"cz_CZ\")). This is a Czech locale.

A SELECT statement works and tak

5条回答
  •  情书的邮戳
    2020-11-30 15:48

    In Android sqlite, LIKE and GLOB ignore both COLLATE LOCALIZED and COLLATE UNICODE (they only work for ORDER BY). However, as @asat explains in his answer, you can use GLOB with a pattern that will replace each letter with all the available alternatives of that letter. In Java:

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

    And then (not literally like this, of course):

    SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"
    

    This way, for example in Spanish, a user searching for either mas or más will get the search converted into m[aáàäâã]s, returning both results.

    It is important to notice that GLOB ignores COLLATE NOCASE, that's why I converted everything to lower case both in the function and in the query. Notice also that the lower() function in sqlite doesn't work on non-ASCII characters - but again those are probably the ones that you are already replacing!

    The function also replaces both GLOB wildcards, * and ?, with "escaped" versions.

提交回复
热议问题