PHP + PostgreSQLで静的プレースホルダを利用する方法も教えて頂けますと助かります。
http://php.net/manual/ja/function.pg-query-params.php
pg_query_params() は PostgreSQL 7.4 以降の接続でのみ サポートされます。
http://www.postgresql.org/docs/7.4/interactive/release-7-4.html
New client-to-server protocol
The new protocol adds ..., parameter values separated from SQL commands, prepared statements available at the protocol level, and ....
また、
https://github.com/php/php-src/blob/master/ext/pgsql/pgsql.c#L1992
http://www.postgresql.org/docs/9.4/static/libpq-exec.html
PQexecParams is supported only in protocol 3.0 and later connections; it will fail when using protocol 2.0.
などからpg_query_params()はプロトコルの静的プレースホルダ対応に依存している事が推察出来き、静的プレースホルダしか対応しないと推察出来る。
したがって、7.4以降を使えば静的プレースホルダを利用出来るはず。
http://lets.postgresql.jp/documents/tutorial/with_php/against_sql_injection/placeholder/pg_xxxx
たしかに、pg_query_params実行時は無名のプリペアドステートメントが使用されている、と書かれているサイトもありました。だとすると
という「安全なウェブサイトの作り方」の記載はなんなのでしょう。。
2015/08/28 21:01:49ソースはC言語です。
2015/08/29 01:16:01phpもC言語で書かれていて、pg_query_params()とかphpのPostgreSQL関連の関数もC言語でpgsql.cに書かれてる。
https://github.com/php/php-src/blob/master/ext/pgsql/pgsql.c
で、このpgsql.cはPostgreSQLのライブラリのlibpq使ってます。そのソースのうち、クエリをサーバに送って実行する系の関数がfe-exec.cにあります。
http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c;hb=HEAD
プリペアドステートメントは文字通り、命令を事前に準備するって事です。
SQLでPREPARE命令って命令文に名前付けて後で呼び出せる命令あります。
これだとサーバに送るのはSQLだけです。パラメータも後でSQL(EXECUTE命令)として送ります。
これもプリペアドステートメントの一つなのですが、結局パラメータをSQLとして送る必要があるので、セキュリティ目的には利用出来ません。
PREPARE命令じゃなくてプロトコル、サーバとのやりとりの仕方で、名前付けて後で利用する方法もあります。
この場合、命令に名前付けたり、送るパラメータはSQLとしてではなく送る事が出来ます。
そのためには、サーバとのやりとりにSQL以外も送ることが可能なプロトコル/APIじゃないと出来ません。
逆に言えば、パラメータをSQLとしてではなく送ることが出来、SQLとして解釈される余地がなくなり、セキュリティ目的に利用出来ます。
これが出来るようになったのが7.4以降のようです。
さて、pg_query_params()で使ってるPQexecParams()はほとんどこのプリペアドステートメントと同じような事をしています。
まずSQL文を送ります。ただ、送った文に名前を付けません。名前がついていないので後で利用出来ません。利用する方法がありません。
その代わり、直ぐにパラメータを送り実行します。
プロトコル的、内部的には事前にサーバにSQL文を送り、直後でもその後にパラメータを送っているので、事前に準備された文ではあります。
ただ、PQexecParams()つまりAPIとしては連続で、1度切りで直ぐに実行しなければならないと言うのは、実質的な意味では事前に準備された文とは呼べないかもしれません。
しかし、値がSQL文としてではなく、プレースホルダを使用しプロトコルとして別々に送られて、サーバ側でバインドされているのでプレースホルダとしてはほぼ静的プレースホルダです。
ただ、ISO/JIS規格としての定義が(狭い意味での)プリペアドステートメントを用いるということなら定義としては静的プレースホルダではないかもしれません。
ただ、それらは字義/定義上での問題で、それがどちらになるにせよ、それで動作や安全性が変わるわけでもなく、サーバにはSQL文とパラメータが別々に送られているので、サーバにバグがない限りは安全でしょう。
と言う所でしょうか。