None of the existing answers are correct.
The Turkish language has multiple representations of the letter I
which are equal from a case-sensitivity point of view. Comparing the lowercase or uppercase forms of these characters will return false.
Georgian has a character ჳ
that has no uppercase equivalent, and a character უ
that has no lowercase equivalent. If you dig into Java's implementation of String.equalsIgnoreCase()
you will find the following code snippet:
// Case insensitive comparison of two code points
private static int compareCodePointCI(int cp1, int cp2) {
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
cp1 = Character.toUpperCase(cp1);
cp2 = Character.toUpperCase(cp2);
if (cp1 != cp2) {
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
cp1 = Character.toLowerCase(cp1);
cp2 = Character.toLowerCase(cp2);
if (cp1 != cp2) {
return cp1 - cp2;
}
}
return 0;
}
Besides, if you'd like to compare strings in a case-insensitive manner you'd likely want to strip out other differences as well. You can use a process called "text normalization" to convert text into a canonical form that strips away accents, punctuation, characters that display the same but have different values, and invisible characters.
The way I personally dealt with this problem is storing two representations for each column that I want to search against:
foobar_display
which corresponds to the original value that the user entered, and is used for display purposes.
foobar_compare
which is used for search and comparison purposes.
Every time that I insert a row into the database I convert foobar_display
into foobar_compareusing a [text normalization library](https://github.com/slugify/slugify). I store both values, and any time a user tries searching for a value I use
foobar_compare` to detect partial or full matches.
Finally, I add a unique constraint against foobar_compare
to unwanted duplicates.