私はimyouというニックネーム管理用gemを公開しているのですが、開発時にPostgreSQLを使っていました。 しかし、RailsのデフォルトのデータベースはSQLiteなので、SQLiteで開発したほうがよかろうと考え、SQLiteに変更してテストを実行したところ、なんと落ちてしまいました。
落ちた原因の調査
テストで実行されているSQLが変わるのか?と思い、to_sql
を挟んで調査してみましたが、SQL文はほぼ同じ。PostgreSQLの場合はILIKE
になるくらい。
落ちていたテストは、LIKE演算子にアンダーバーを含んだ文字列でした。sanitize_sql_like
メソッドを使っているから、_
もしっかりエスケープされているから問題ないはず…。と思っていたのですが、どうもSQLiteでは、明示的にESCAPE文字列を指定しないといけないようでした。PostgreSQLでも明示的に指定はできますが、デフォルトは\
(バックスラッシュ)です。
明示的に指定していないため、エスケープされた文字列はfoo\_bar
のようになっているものの、バックスラッシュと任意の一文字と合致する条件となってしまっていました。
対処
sanitize_sql_like
メソッドの第二引数はエスケープ文字の指定なので、'\\'
を指定するように修正しました。
こうすることで、WHERE name LIKE '%foo\_bar%' ESCAPE '\'
というSQLに変わり、SQLiteでも問題なくエスケープされるようになりました。
まとめ
SQLiteで_
を含むパターンマッチを行う場合はエスケープ文字をちゃんと設定しましょう。
なお、imyouは、この問題を修正したバージョン 1.4.2 をリリース済みです。