読者です 読者をやめる 読者になる 読者になる

RailsのSQLiteで正規表現を使う

rails sqlite

Postgres や MySQL では、書き方は違えど正規表現を使うことができます。 しかし、RailsのDevelopment(SQLite)で実行すると、エラーとなります。

SQLite3::SQLException: no such function: REGEXP

SQLiteでのREGEXP

こちらを見てみると SQLite3におけるREGEXP演算子 - めらんこーど地階

The REGEXP operator is a special syntax for the regexp() user function. 
No regexp() user function is defined by default and so use of the REGEXP operator 
will normally result in an error message. If an application-defined SQL function 
named "regexp" is added at run-time, then the "X REGEXP Y" operator will be 
implemented as a call to "regexp(Y,X)".

SQLite Query Language: expression を見てみると
確かに、application-defined SQL function で regexp を追加しろと記載があります。

Rails ではどうすれば良いか?

ググるとこちらのgemがありました。
Rails5でとりあえず動作するようにgemspecを修正したPRを出したら速攻で取り込んでもらえたので
今はGemfileに突っ込んだら使える状態です。
AaronLasseigne/sqlite3_ar_regexp

(以下のケースでは REGEXP 使う必要はないのですが、)
とりあえず動作するかどうかを見るために手元で動かしてみました。

names = ["ジェイミー・ヴァーディ", "中村憲剛"]
Person.where("name REGEXP :names", names: names.join("|"))

以下のSQLが発行されます。 REGEXP が使用されているのが分かります。

SELECT "people".* FROM "people" WHERE (name REGEXP 'ジェイミー・ヴァーディ|中村憲剛')

どうやってるの?

sqlite3_ar_regexp/extension.rb at master · AaronLasseigne/sqlite3_ar_regexp
を見ると以下を利用しています。

connection.create_function('regexp', 2) do |func, pattern, expression|

てっきり SQLite側に仕込む必要があるかと思ったのですが、各種driver側でユーザ定義関数を作成できるメソッドがそれぞれ用意されているようでした。
sqlite3 だと以下。 Method: SQLite3::Database#create_function — Documentation for luislavena/sqlite3-ruby (master)

まとめ

とりあえず使ってみたい人向け。速度などは未検証。