指定されたロケールでsqlite3のテキストをソートする方法は?
-
03-07-2019 - |
質問
Sqlite3は、デフォルトではASCII文字のみでソートします。グーグルで調べてみましたが、私が見つけたのは照合に関する情報だけでした。 Sqlite3には、 NOCASE
、 RTRIM
、および BIARY
の照合のみがあります。特定のロケールのサポートを追加する方法は?
(私はRailsアプリケーションで使用しています)
解決
SQLite サポート ICU 。 Readmeファイルによると、
sqlite / ext / icu / README.txt
sqlite / ext / icu /
ディレクトリには、SQLite" ICU"のソースコードが含まれています。拡張、
「Unicodeの国際コンポーネント」の統合SQLiteを使用したライブラリ。
1. Features
1.1 SQL Scalars upper() and lower()
1.2 Unicode Aware LIKE Operator
1.3 ICU Collation Sequences
1.4 SQL REGEXP Operator
他のヒント
Doug Currieの回答を受け入れましたが、「アルゴリズム」を追加します。 sqlite3のドキュメントは非常に奇妙です(少なくとも私にとっては)。
OK、作業中のsqlite3があります:
-
コンパイル:
gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so
これはLinux用です。また、追加のICU開発パッケージをインストールする必要がありました。
sudo apt-get install libicu-dev
64ビットアーキテクチャで作業していますが、
__ relocation R_X86_64_32S __
でエラーが発生します(意味は何でも)。 GCCは、オプションをコンパイルするために-fPIC
を追加することを提案し、それが役立ちました。 -
sqlite3を実行します。コマンドで拡張機能をロードできます:
.load './libSqliteIcu.so'
現在のディレクトリにあると仮定して、パス全体を指定することもできます。
-
新しい照合の作成:
SELECT icu_load_collation('pl_PL', 'POLISH');
最初のパラメーターは目的のロケールであり、2番目はそれです(何でも構いません)。
-
新しいロケールでデータをソートできるようになりました:
SELECT * FROM some_table ORDER BY name COLLATE POLISH;
そして、大文字と小文字は区別されません!
ICU拡張をコンパイルする余裕がない場合は、UDFに同じことをさせることができます。 PHP / PDOの場合:
$pdo->sqliteCreateFunction('locale',
function ($data, $locale = 'root')
{
static $collators = array();
if (isset($collators[$locale]) !== true)
{
$collators[$locale] = new \Collator($locale);
}
return $collators[$locale]->getSortKey($data);
}
);
使用例:
SELECT * FROM "table" ORDER BY locale("column", 'pt_PT');
このアプローチがネイティブ拡張ほど効率的であるとは思わないが、確実に移植性が高い。
自分で拡張機能を構築できない人のために、コンパイル済みバージョンをmacOSおよびLinuxで利用できるようにしました: http://files.tempel.org/Various/Sqlite3ICUExtention
Intel 32ビットと64ビットの両方のLinuxバージョンは、Ubuntu 16で構築されています(それが重要な場合)。
一般に、他の人から提供されたコンパイル済みのコードを信頼するべきではありませんが、私は非常に公的な人です。つまり、「悪い」を提供すると、かなりのリスクを冒すことになります。バージョン。そして、私のサーバーに対して中間者攻撃やハッキングが行われないようにするために、3つのファイルのMD5ハッシュを以下に示します。
libSqliteIcu-i386.so = 6decd73f27d9c61243128e798304508f
libSqliteIcu-x86_64.so = b127c8a1f65503c91c61a21732eb11be
sqlite3_icu_extension.dylib = a29d59f6b74e7ef234691729b82da660