これはバグではなく、機能です...ここには2つのポイントがあります。
-
'now'の置換
ドキュメントを見てみましょう( Date /Time関数と演算子 ):
したがって、
'now'
解析時にタイムスタンプに変換されます。 -
プリペアドステートメント
さて、しかしそれは機能に関してどういう意味ですか?関数を呼び出すたびに、関数が解釈されることを示すのは簡単です。
t=# create function test() returns timestamp as $$ begin return 'now'; end; $$ language plpgsql; CREATE FUNCTION t=# select test(); test ---------------------------- 2015-12-11 11:14:43.479809 (1 row) t=# select test(); test ---------------------------- 2015-12-11 11:14:47.350266 (1 row)
この例では、
'now'
期待どおりに動作します。違いはなんですか?関数はSQLステートメントを使用しますが、test()は使用しません。ドキュメントをもう一度調べてみましょう( PL / pgSQLプランキャッシング ):
そしてここ(プリペアドステートメント ):
したがって、
'now'
プリペアドステートメントが解析されたときにタイムスタンプに変換されました。関数の外部でプリペアドステートメントを作成して、これを示しましょう。t=# prepare s(integer) as UPDATE test_date_bug SET date2 = 'now' WHERE id = $1; PREPARE t=# execute s(1); UPDATE 1 t=# execute s(2); UPDATE 1 t=# select * from test_date_bug; id | date1 | date2 ----+-------------------------------+------------------------------- 3 | 2015-12-11 11:01:38.491656+03 | infinity 1 | 2015-12-11 11:01:37.91818+03 | 2015-12-11 11:40:44.339623+03 2 | 2015-12-11 11:01:37.931056+03 | 2015-12-11 11:40:44.339623+03 (3 rows)
それが起こったのです。 'now'
(プリペアドステートメントが解析されたときに)タイムスタンプに1回変換され、now()
2回呼び出されました。