Skip to content

Instantly share code, notes, and snippets.

@ap-Codkelden
Last active May 17, 2017 09:19
Show Gist options
  • Save ap-Codkelden/c5c0b8d1ed775238102eef6e2f482962 to your computer and use it in GitHub Desktop.
Save ap-Codkelden/c5c0b8d1ed775238102eef6e2f482962 to your computer and use it in GitHub Desktop.
ICU How To
# Регистронезависимый LIKE в SQLite для кириллицы
Original is [here](https://medium.com/@eigenein/%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%BE%D0%BD%D0%B5%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D1%8B%D0%B9-like-%D0%B2-sqlite-%D0%B4%D0%BB%D1%8F-%D0%BA%D0%B8%D1%80%D0%B8%D0%BB%D0%BB%D0%B8%D1%86%D1%8B-95e3e33e8ad)
При использовании `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, )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment