PostgreSQL timestamp / числовая точность игнорируется на параметре функции?
Даны следующие функции PostgreSQL:
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;
Ожидаете ли вы, что выходные данные этих функций будут показывать результат в соответствии с типом, объявленным в параметре функции?
Я был очень удивлен, обнаружив, что точность была сохранена и показана в "уведомлении", несмотря на тип параметра, ограничивающий точность.
Это ошибка или я просто думаю об этом неправильно?
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
Я использую 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;
Дает:
db=> SELECT fn_dtm(now());
NOTICE: fn: 2015-02-05 10:38:38+00
1 ответ:
Возможно, это не то, что вы ожидаете, но именно так это работает.
Причина ясна, если вы спросите Postgres для определения функции; запустите
\sf fn_num
в psql илиSELECT pg_get_functiondef('fn_num'::regproc)
, и он даст вам:Таким образом, к тому времени, когда Postgres создает вашу функцию, информация о точности/масштабе уже отброшена. Типы возвращаемых данных страдают от той же проблемы.CREATE OR REPLACE FUNCTION public.fn_num(num numeric) ...
Это можно обойти, используя домены для псевдонимов типов, участвующих:
CREATE DOMAIN timestamptz_seconds AS timestamptz(0); CREATE FUNCTION fn_dtm(dtm timestamptz_seconds) ...
Это может быть особенно полезно для типов возвращаемых данных, если требуется сохранить точность определения результирующего набора. Но в большинстве случаев, как вы уже отмечали, вы можете получить тот же результат с некоторыми явными приведениями в вашем функциональном теле.