From: | Mark Simonetti <marks(at)opalsoftware(dot)co(dot)uk> |
---|---|
To: | pgsql-bugs(at)postgresql(dot)org |
Subject: | Function parameter type precision modifiers ignored. |
Date: | 2015-02-05 16:46:02 |
Message-ID: | 54D39E4A.9030600@opalsoftware.co.uk |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
Hi,
I don't know if this is a bug as such, but the behaviour certainly
confused me for a while : -
Given the following PostgreSQL functions:
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'fn: %, %', dtm, dtm::timestamptz(0);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION fn_num (
num numeric(5, 2))
RETURNS void AS $$
BEGIN
RAISE NOTICE 'num: %, %', num, num::numeric(5, 2);
END;
$$ LANGUAGE plpgsql;
Would you expect the output of these functions to show the result as per
the type declared in the function parameter?
I was very surprised to find that the precision was retained and shown
in the "NOTICE" despite the parameter type limiting the precision.
Is this a bug or am I just thinking about it the wrong way?
Here is the output:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:25:44.184+00, 2015-02-05 10:25:44+00
db=> SELECT fn_num(1.23456789);
NOTICE: num: 1.23456789, 1.23
I am using PostgreSQL 9.3.
CREATE OR REPLACE FUNCTION fn_dtm (
dtm timestamptz(0))
RETURNS void AS $$
BEGIN
dtm = dtm::timestamptz(0); ----- CHANGE PRECISION
RAISE NOTICE 'fn: %', dtm;
END;
$$ LANGUAGE plpgsql;
Gives:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:38:38+00
I don't know if the behaviour is documented anywhere (sorry if I've
missed it), but not knowing this really confused me for a good couple of
hours. For fun here was the scenario : -
1) For my monitoring system I have a readings table. In my readings
table I store the timestamp only to a 1 second precision (timestamptz(0)).
2) When a new "live" reading comes in, I use "now()" to get the
timestamp. I then pass this to another function with the reading
parameters, including a time argument (of type timestamptz(0)) which
gets passed now()). Lets say now() is 2015-02-05 16:35:38.923.
3) The new reading gets stored in the database, and since the field type
is timestamptz(0) it gets rounded up to (2015-02-05 16:35:39).
4) If the new reading indicates an alarm state, I do a pg_notify to send
an event to my app which includes the passed in timestamp. Now I
assumed because of the parameter type this would not include
milliseconds, so naturally I ignore anything after the seconds when I
parse the notification event.. So I end up with 2015-02-05 16:35:38.
Spot the difference to the stored timestamp?
5) The application then periodically loads the readings in alarm from
the database based on the events received. So I do SELECT ..... WHERE
reading_dtm = '2015-02-05 16:35:38' etc. Obviously nothing is returned
as the timestamp is out by one second (except where the original reading
timestamp was not rounded up).
I've fixed it by just doing p_reading_dtm =
p_reading_dtm::timestamptz(0) at the start of my function. Seems odd
though when the parameter type is already timestamptz(0).
Regards,
Mark.
--
From | Date | Subject | |
---|---|---|---|
Next Message | Heikki Linnakangas | 2015-02-05 21:17:46 | pg_receivexlog sometimes fails on first start |
Previous Message | krzbia | 2015-02-05 12:02:30 | BUG #12738: Would not install on Windows XP - wrong platform - should be v110_xp instead ov v110 |