やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

SQLite3拡張 ICUでcollateする

 照合シーケンス。ロケール固有の文字列比較。

成果物

前提

 SQLite3を用意する。

 ICUを有効にする。静的・動的どちらでもいい。

API

 icu.cのコメントに使い方が書いてあった。

SQL関数 概要
A LIKE B LIKE
contains(zPattern, zString) 含まれているか否か
regexp(zPattern, zString) 正規表現
lower('I'), lower('I', 'en_us') 小文字化
upper('i'), upper('i', 'en_us') 大文字化
icu_load_collation('jp_JP','japanese') collation設定

regexp()

select regexp('[\d]+[\w]+[\d]+', '12abc34');
1
select regexp('[\d]+[\d]+', '12abc34');
0

 指定した正規表現に一致していたら1、そうでないなら0を返す。

contains()

begin transaction;
create table myTable(myColumn text);
insert into myTable values('e');
insert into myTable values('é');
insert into myTable values('è');
insert into myTable values('é');
insert into myTable values('ê');
insert into myTable values('ë');
insert into myTable values('E');
insert into myTable values('Ê');
insert into myTable values('É');
commit;
select * from myTable where contains ('e', myColumn);
e
é
è
ê
ë
E
Ê
É

icu_load_collation()

select icu_load_collation('ja_JP','japanese');
select 1 collate japanese;
create table posts(title text);
insert into posts values('');
insert into posts values('');
insert into posts values('');
insert into posts values('');
insert into posts values('バ');
insert into posts values('');
insert into posts values('');
insert into posts values('パ');
select * from posts where title='パ' collate japanese;
パ
select * from posts where title='' collate japanese;
ぱ
パ
select * from posts where title='' collate japanese;
ぱ
パ

 を同一とみなした。collateを外すと以下のように異なるものとみなす。

select * from posts where title='';

 collateしたときの期待値が違う。パを同じとみなして欲しかった。

パ
パ

 半角カタカナが厄介者。こいつを全角カタカナと比較させて一致したいのに……。ふつうの要件はこれではないだろうか……。

 以下も同じ。

insert into posts values('アパート');
insert into posts values('アパート');
insert into posts values('');
select * from posts where title='アパート'
アパート

 全件出て欲しいのに……。

 like句を使っても同じ。

select * from posts where title like 'アパート';
アパート

 解決方法は不明。以下でなんとかなるのか? 関係ない?

lower(), upper()

select lower('A');
a
select upper('a');
A

 ひらがなやカタカナでは変化なし。

select lower('');
select upper('');
select lower('');
select upper('');
select lower('');
select upper('');
select lower('', 'ja_JP');
select upper('', 'ja_JP');
select lower('', 'ja_JP');
select upper('', 'ja_JP');
select lower('', 'ja_JP');
select upper('', 'ja_JP');
select lower('', 'japanese');
select upper('', 'japanese');
select lower('', 'japanese');
select upper('', 'japanese');
select lower('', 'japanese');
select upper('', 'japanese');

 期待値としては半角カタカナと全角カタカナを相互変換して欲しかった。

情報源

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux

前回まで