
Регистронезависимый LIKE в SQLite для кириллицы
При использовании LIKE или ORDER BY в SQLite с Unicode-символами может возникнуть проблема, связанная с неспособностью SQLite по умолчанию правильно воспринимать разные регистры одной и той же буквы:
sqlite> select "ы" like "ы";
1
sqlite> select "Ы" like "ы";
0
Поиск приводит к расширению ICU, которое переопределяет функции изменения регистра так, чтобы символы за пределами таблицы ASCII правильно приводились к заданному регистру.
Есть два варианта использования расширения:
- Скомпилировать SQLite вместе с расширением (и использовать вместо системной библиотеки).
- Скомпилировать расширение как Runtime Loadable Extension.
Мне хотелось использовать расширение через стандартный модуль sqlite3 в Python, поэтому было решено пойти по второму пути.
Для начала установим необходимые пакеты с исходным кодом:
$ sudo apt-get install libicu-dev libsqlite3-dev
Скачаем исходный код самого расширения:
$ wget "https://www.sqlite.org/src/raw/ext/icu/icu.c?name=b2732aef0b076e4276d9b39b5a33cec7a05e1413" -O icu.c
А дальше — немного странный момент. Если мы сейчас скомпилируем расширение, то вероятно, получим следующую ошибку при попытке загрузить его (имя в вашей версии SQLite может быть другим):
sqlite> .load ./libsqliteicu.so
Error: ./libsqliteicu.so: undefined symbol: sqlite3_sqliteicu_init
Чтобы исправить ошибку, редактируем файл icu.c, заменяя в нем имя функции sqlite3_icu_init на sqlite3_sqliteicu_init.
Теперь собираем расширение:
$ gcc -shared icu.c -g -o libsqliteicu.so -fPIC `icu-config --cppflags --ldflags`
Загружаем расширение и проверяем, что все в порядке:
sqlite> .load ./libsqliteicu.so
sqlite> select "Ы" like "ы";
1
Бонус
Для того, чтобы загрузить это расширение из Python, сначала разрешаем загрузку расширений из библиотек и затем загружаем саму библиотеку:
import sqlite3
connection = sqlite3.connect(":memory:")
connection.enable_load_extension(True)
connection.load_extension("./libsqliteicu.so")
assert connection.execute("select 'ы' like 'Ы'").fetchone() == (1, )
Originally published at eigenein.xyz on December 27, 2015.