Можно настроить функции с перегрузкой подтипа? - PullRequest
0 голосов
/ 14 сентября 2018

При использовании CREATE TABLE можно объявить типы данных varchar(12), varchar(34) или varchar, и они будут другими ...

Но при объявлении функции "подтип" игнорируется ... Нет предупреждения (!) ...
Я вижу, что игнорировать - это хорошо, сигнатура функции необходимо управлять перегрузкой функций , и «подписи подтипов» будут чем-то хаотичным в управлении ... Но я не вижу в Руководстве (также ничего в typeconv-func ), нет Предупреждение гида об этом, без объяснений.

Итак, в наши дни 2018 год, после всех улучшений PostgreSQL v10 + ... Можно ли настроить PostgreSQL для приема перегрузки функций с подтипами?


Конкретный пример

CREATE TABLE foo ( x  varchar(12), y varchar(34), z varchar );
\d foo
-- not ignored, as expected 

CREATE OR REPLACE FUNCTION foo( p_x varchar ) RETURNS text AS 
$f$ SELECT 'hello1' $f$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION foo( p_x varchar(12) ) RETURNS text AS 
$f$ SELECT 'hello10' $f$ LANGUAGE SQL IMMUTABLE;

\df foo
                           List of functions
 Schema | Name | Result data type | Argument data types   |  Type  
--------+------+------------------+-----------------------+--------
 public | foo  | text             | p_x character varying | normal
 (1 row)

Так что невозможно объявить foo(x), что не делают того же самого foo(z) ...

 SELECT pg_typeof(x),pg_typeof(y),pg_typeof(z) FROM foo;
 -- returns "character varying" for all

Конечно, иногда мы можем использовать pg_typeof():

  • С VARCHAR (s) невозможно проверить s.
  • С PostGIS можно geometry проверить подтип (например, подтип POINT). Это перегрузка обходной путь, но не "реальная перегрузка ".

ПРИМЕЧАНИЕ : ошибка синтаксического анализа с комментарием foo('abc') будет устранена с помощью соответствующего ортогонального набора функций перегрузки ". В примере с

CREATE FUNCTION foo( p_x text ) RETURNS text AS $f$ SELECT 'hello-text' 
$f$ LANGUAGE SQL IMMUTABLE;

"автоматическое приведение abc к тексту" решает проблему select foo('abc') работает.

1 Ответ

0 голосов
/ 14 сентября 2018

«Подтип» - это модификатор типа , обычно называемый typmod.

Когда вы создаете функцию с typmods в сигнатуре, они просто игнорируются.В каталоге функций хранятся только идентификаторы базового типа (в отличие от каталога столбцов , в котором есть поле atttypmod), поэтому нет возможности дифференцировать две функции только с помощью typmod.

Насколько я знаю, единственным обходным решением является создание домена (пользовательский псевдоним типа со встроенным typmod).Это позволяет вашей функции ссылаться на typmods без необходимости хранить их в pg_proc:

CREATE DOMAIN varchar12 AS varchar(12);
CREATE OR REPLACE FUNCTION foo( p_x varchar12 ) RETURNS text AS 
$f$ SELECT 'hello10'::text $f$ LANGUAGE SQL IMMUTABLE;

Мотивация для этого обычно состоит в том, чтобы сохранить ограничение длины;Ваша varchar(12) функция будет принимать строку из 1000 символов без жалоб.

Но хотя типы доменов позволяют перегрузить вашу функцию, вам все равно необходимо преобразовать значения в соответствующий тип домена, чтобы разрешитьперегрузка.

Так что это, вероятно, мало практического применения, если только вы не хотите конвертировать столбцы таблицы в домены.(Определение вашей схемы в терминах доменов имеет свои преимущества, если вы выбираете более значимые имена, чем varchar12.)

...