Обсуждение: Function parameter type precision modifiers ignored.

Поиск
Список
Период
Сортировка

Function parameter type precision modifiers ignored.

От
Mark Simonetti
Дата:
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.
--

Re: Function parameter type precision modifiers ignored.

От
Tom Lane
Дата:
Mark Simonetti <marks@opalsoftware.co.uk> writes:
> 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?

Attributes applied to function parameter types --- or result types for
that matter --- are entirely ignored by Postgres; only the base type
matters.  This is documented.

There's been some talk of rejecting syntax like the above, because we
get bug reports like this once or twice a year, so obviously a lot of
people are confused about what happens.

The odds of actually enforcing such typmods anytime in the near future
are not distinguishable from zero, but we could make CREATE FUNCTION
throw an error.

            regards, tom lane

Re: Function parameter type precision modifiers ignored.

От
David G Johnston
Дата:
Tom Lane-2 wrote
> Mark Simonetti <

> marks@.co

> > writes:
>> 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?
>
> Attributes applied to function parameter types --- or result types for
> that matter --- are entirely ignored by Postgres; only the base type
> matters.  This is documented.

http://www.postgresql.org/docs/9.4/interactive/sql-createfunction.html
@ Notes
First Paragraph

Maybe it would be more obvious in the section detailing "argtype"...but its
not like its buried deep in the documentation.  The bigger problem is
understanding exactly what that notes means in reality.  Often that means
getting bit by the behavior first and then reading about what just bit you.
Happens to all of us.

I'm for the idea of issuing a syntax error upon seeing "type()" in general
but not strongly since perfectly valid code (often back-stopped by table
constraints) currently works and would otherwise have no reason to change
other than to conform to this decision.

David J.



--
View this message in context:
http://postgresql.nabble.com/Function-parameter-type-precision-modifiers-ignored-tp5836988p5837000.html
Sent from the PostgreSQL - bugs mailing list archive at Nabble.com.

Re: Function parameter type precision modifiers ignored.

От
Tom Lane
Дата:
David G Johnston <david.g.johnston@gmail.com> writes:
> Tom Lane-2 wrote
>> Attributes applied to function parameter types --- or result types for
>> that matter --- are entirely ignored by Postgres; only the base type
>> matters.  This is documented.

> Maybe it would be more obvious in the section detailing "argtype"...but its
> not like its buried deep in the documentation.  The bigger problem is
> understanding exactly what that notes means in reality.  Often that means
> getting bit by the behavior first and then reading about what just bit you.
> Happens to all of us.

> I'm for the idea of issuing a syntax error upon seeing "type()" in general
> but not strongly since perfectly valid code (often back-stopped by table
> constraints) currently works and would otherwise have no reason to change
> other than to conform to this decision.

Another possibility is to issue a WARNING or NOTICE rather than hard
error.

            regards, tom lane