Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL timestamp/numeric precision ignored on function parameter?

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.

EDIT: If I do this I get what I expect:

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
like image 836
Mark Avatar asked Jan 24 '26 19:01

Mark


1 Answers

It's probably not what you'd expect, but that's the way it works.

The cause is clear if you ask Postgres for the function's definition; run \sf fn_num in psql, or SELECT pg_get_functiondef('fn_num'::regproc), and it will give you:

CREATE OR REPLACE FUNCTION public.fn_num(num numeric) ...

So by the time Postgres creates your function, the precision/scale information has already been discarded. Return types suffer from the same issue.

It is possible to work around this by using domains to alias the types involved:

CREATE DOMAIN timestamptz_seconds AS timestamptz(0);
CREATE FUNCTION fn_dtm(dtm timestamptz_seconds) ...

This can be particularly useful for return types if you need to retain the precision in the definition of your result set. But in most cases, as you pointed out, you can get the same outcome with some explicit casts in your function body.

like image 73
Nick Barnes Avatar answered Jan 26 '26 10:01

Nick Barnes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!