PostgreSQLでprepare

prepareというのは、SQLの実行の際に「まずテンプレートを用意してから内容を流し込む」ようなやり方のこと。本当は処理の高速化のための機能なのだが、SQLインジェクションとかを回避するためにも使われる。*1

で、作りかけのプログラムで使っているprepareが「原因不明のエラー」を返してくるので、直接PostgreSQLのコンソールで対話実行してみると…全く分からないことが分かった。

prepare test as INSERT INTO "tablename" ("col1","col2","col3") VALUES (?,?,?);

という指示をすると、一つ目のクエッションマークの次のところで文法エラーになるのである。


というわけでPostgreSQLのマニュアルを参照すると…
"旧バージョン"
"新バージョン"

旧バージョンのマニュアルは全く例示が無くて使い物にならず、新バージョンのマニュアルでも、「省略可能なデータ型指定部分」を省略した時にどうするのかが全く書かれていない。

ちなみにマニュアルの例通り

prepare test (text,text,boolean) as INSERT INTO "tablename" ("col1","col2","col3") VALUES ($1,$2,$3);

とすると何事もなく通る。


今回は別に型チェックなんてしたくないし、型を指定しなくてもかけるはずなのだが…

それとも型チェックなしのPREPAREを認めていないのか?なんかそんな気がしてきた。本来の存在理由では型指定がないのはおかしいので。しかし、今からそれに合わせて作り替えることは出来ないんですが。*2


そもそも『標準SQLのPREPARE文では多少異なる構文が使用されます。』とあるにもかかわらず、独自仕様については解説がないの?とか思いつつ検索中…

*1:SQLインジェクションの基本は「本来単なる値であるはずのものを制御構造として誤認させる」ことにあるのだが、preparedされたSQL文では値として指定されているものは値以外にはなれないので、インジェクションが成立しない…はずである。

*2:現状、プログラム側には型の情報が入力されていない。データベース側には当然設定されているのだが。ほぼ全部に手を入れれば対応可能だが…手間過ぎる。まぁ、単にprepareを諦めてエスケープ処理にすればいいんですけど。あるいは、データベース定義から自動的に型情報を取り出してきて指定するプログラムを書く。出来そうな気もするが、そこまでやる気は起きないなぁ