Чтобы начать работу с ICU экстеншеном, сначало его нужно скомпилировать в динамическую библиотеку.
Для этого понадобится библиотека поддержки юникода icu, и сам код ICU экстеншена:
Для Mac OS(при условии что установлен macports):
$ sudo port install icu
$ wget http://www.sqlite.org/cvstrac/getfile?f=sqlite/ext/icu/icu.c
$ gcc -dynamiclib icu.c -o libsqliteicu.dylib `icu-config --cppflags` `icu-config --ldflags`
Либо Debian:
$ sudo apt-get install libicu-dev
$ wget http://www.sqlite.org/cvstrac/getfile?f=sqlite/ext/icu/icu.c
$ gcc -shared icu.c -o libsqliteicu.so `icu-config --cppflags` `icu-config --ldflags`
Теперь запускаем SQLite3 CLI, и радуемся результату:)
$ sqlite3
загружаем расширение
sqlite> .load libsqliteicu.dylib
устанавливаем русский collation
sqlite> SELECT icu_load_collation('ru_RU', 'RUSSIAN');
sqlite> SELECT "ы" LIKE "Ы";
1
Но, в итоге все оказывается не так то просто. Чтобы загрузить экстеншн через API а не через CLI, нужно вызвать функцию
sqlite3_enable_load_extension. Если драйвер SQLite для вашего языка имеет обертку для этой функии, или же вы пишите на C/C++ — то все в порядке. Но вот дравер для Ruby, ruby-sqlite3, данную функцию не поддерживает…
Первая мысль — добавить эту функцию в драйвер:) Но, нашелся вариант по-проще. Оказывается, ICU расширение можно встроить в SQLite.
$ wget http://www.sqlite.org/sqlite-amalgamation-3.6.13.tar.gz
$ tar xzfv sqlite*
$ cd sqlite*
$ CFLAGS='-Os -DSQLITE_ENABLE_ICU' CPPFLAGS=`icu-config --cppflags` LDFLAGS=`icu-config --ldflags` ./configure
$ make && sudo make install
После этого переустанавливаем адаптер для Ruby(чтобы пересобрался), и радуемся решению проблемы:)
Но, естественно не обошлось и без минусов. Из-за зависимости от ICU, библиотека будет весить несколько мегабайт, что не очень хорошо для embed базы данных. Если же sqlite используется для сайта(как в моем случае), то это волновать не должно.
Решением может быть создание собственного collation с помощью
sqlite3_create_collation.
UPD: Для тех кто использует Ruby библиотеку Sequel. Как я сказал выше, ICU экстеншн также добавляет оператор REGEXP. Но, если в Sequel попытаться выполнить запрос с регулярными выражениями, например так
p DB[:artists].filter(:name => /^a.*/i).all
то кинется эксепшн, о том, что SQLite не поддерживает регулярные выражение.
Чтобы это обойти, я написал небольшой
monkey patch.