[groonga-dev,02203] PHPなどによる検索文字列エスケープの基準

Back to archive index

Kimura A a.kim****@live*****
2014年 3月 30日 (日) 18:46:30 JST


お世話になっています。素人プログラマーの木村です。
以下の記事を参考にmroonga_escape()の導入を検討していたのですが、ちょっと判断に迷ってしまったのでご相談してみることにしました。
http://qiita.com/groonga/items/8393520a7eff5a71dd57


たとえば以下のようなクエリをDBに送りたい場合、DB側で処理されるmroonga_escape()は使い方が難しいように思います。

SELECT * FROM `table_name` 
WHERE MATCH(`target_column`) 
AGAINST(
    '+Word1_()_withBrackets +(Word2_"_withQuote Word3_+_withPlus) -Word4_-_withMinus' IN BOOLEAN MODE
);

このクエリの目的は、以下の条件に合ったレコードを取得することです。
・「Word1_()_withBrackets」を含む
・「Word2_"_withQuote」または「Word3_+_withPlus」を含む
・「Word4_-_withMinus」を含まない

これに単純にmroonga_escape()を加筆して、

SELECT * FROM `table_name` 
WHERE MATCH(`target_column`) 
AGAINST(
    mroonga_escape(
        '+Word1_()_withBrackets +(Word2_"_withQuote Word3_+_withPlus) -Word4_-_withMinus'
    ) IN BOOLEAN MODE
);

のようにしてしまうと、結果的には

SELECT * FROM `table_name` 
WHERE MATCH(`target_column`) 
AGAINST(
    '\\+Word1_\\(\\)_withBrackets \\+\\(Word2_\\"_withQuote Word3_\\+_withPlus) \\-Word4_\\-_withMinus' IN BOOLEAN MODE
);

というクエリを送ったのと同じことになってしまって、所期の目的を果たすことができません(詳しい仕様は理解していませんが、実験してみた範囲ではそのような挙動に見えます)。


なので、できればプログラム(PHP)側でmroonga_escape()近似の処理を行いたいと思っています。
たとえば以下のように、あらかじめ準備したPHP関数mroongaEscapeで問題のある記号をエスケープして、

$word1 = mroongaEscape('Word1_()_withBrackets');

その上でこの変数$word1をクエリに組み込めば、安全に複合条件での検索を行える、という具合にしたいわけです。

そこで質問なのですが、この場合、PHP関数mroongaEscapeはどのような挙動を満たすべきでしょうか?
ガイドライン的なものがぜひ欲しいです。今のところ、
・「'"()~+><-*」に「\\」を前置する
・ただし、それらの記号にあらかじめ「\」が前置されている場合は処理対象としない
というような感じで考えているんですが(いざ実装しようとすると、なかなか難しくて苦戦中です…)。

またこれを適用する場合、素のMySQL仕様に準拠したエスケープ処理(PHPにおけるmysqli::real_escape_string()など)は特にしなくて大丈夫ですよね?
盲点になりやすいポイントなどあればご示唆いただけると助かります。


以上、アドバイスどうぞよろしくお願いしますm(_ _)m 		 	   		  



groonga-dev メーリングリストの案内
Back to archive index