さて、dblink での Sanitize。
8/5の日記では prepare を使えばいいと書いたが、
dblink では文字列で渡すわけだから結局問題を解決できない。
そういうわけで、文字列を escape するようにしていく。
 postgresql には文字列を escape する関数 quote_literal がある。
これを使えばすぐだろう。
・・・って考えは甘かった。

 dblink では query を文字列で渡す。

SELECT foo(’XXX’,yyy)

を dblink に埋め込むと

dblink(’SELECT foo(’’XXX’’,yyy)’)

って感じになる。ここで、xxx,yyy を変数にすると

dblink(’SELECT foo(’’’ || v_xxx || ’’’,’ || v_yyy::text || ’)’)

って感じ。これを Stored Function に埋め込むと

dblink(’’SELECT foo(’’’’’’ || v_xxx || ’’’’’’,’’ || v_yyy::text || ’’)’’)

と ’ がいっぱいになってかなり変態的。
で、ここで、quote_literal を入れてみる。

dblink(’’SELECT foo(’’’’’’ || quote_literal(v_xxx) || ’’’’’’,’’ || v_yyy::text || ’’)’’)

ってやったら・・・エラーが出て動かなくなった。
で、なかなか解決できない。うぐぐぐぐ・・・・。

 PHP の場合、pg_escape_string という、
「文字列中の Single Quote 等を escape する」関数があるが、
それはこんな感じで使う。

$sql = "SELECT foo(’" . pg_escape_string($xxx) . "’,$yyy);";

しかし、PostgreSQL の quote_literal は
実は「文字列を引用符で括る」関数で、
ついでに 「文字列中の Single Quote 等を escape する」関数だった。

そういうわけで、正しくは

dblink(’’SELECT foo(’|| quote_literal(v_xxx) || ’’,’’ || v_yyy::text || ’’)’’)

と少しすっきりした形が正しかった。
これだけで半日つぶしたよぉ・・・・。

コメント