To nie jest błąd, to funkcja... Są tu dwie kwestie.
-
Zastąpienie „teraz”
Zajrzyjmy do dokumentacji (Data /Funkcje i operatory czasu ):
Więc
'now'
jest konwertowany na znacznik czasu w czasie analizy. -
Przygotowane oświadczenia
No dobrze, ale co to oznacza w odniesieniu do funkcji? Łatwo zademonstrować, że funkcja jest interpretowana za każdym razem, gdy ją wywołasz:
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)
W tym przykładzie
'now'
zachowuje się zgodnie z oczekiwaniami.Jaka jest różnica? Twoja funkcja używa instrukcji SQL, a test() nie. Przyjrzyjmy się jeszcze raz dokumentacji (PL/ Buforowanie planu pgSQL ):
I tutaj (Przygotuj oświadczenie ):
Stąd
'now'
został przekonwertowany na znacznik czasu podczas analizowania przygotowanej instrukcji. Zademonstrujmy to, tworząc przygotowaną instrukcję poza funkcją: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)
Tak się stało. 'now'
został raz przekonwertowany na znacznik czasu (gdy przygotowana instrukcja była analizowana), a now()
został wywołany dwukrotnie.