可以用子类型重载配置功能吗?

时间:2018-09-14 08:39:56

标签: postgresql overloading

使用CREATE TABLE时,可以声明varchar(12)varchar(34)varchar数据类型,并且它们会有所不同...

但是在声明函数时,“子类型”将被忽略...没有警告(!)...
我发现忽略函数签名是一件好事这对于管理function overloading是必不可少的,“子类型签名”的管理将有些混乱……但是我在《指南》中没有看到(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
  • 使用PostGIS的geometry可以检查子类型(例如POINT子类型)。这是一个超载解决方法,但不是“真正的超载”。

注意:带有适当注释的orthogonal重载函数集将解决带有注释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 :(得分:2)

“子类型”是类型修饰符,通常称为typmod。

当您在签名中创建带有typmods的函数时,它们将被忽略。 function catalog仅存储基本类型ID(不同于column catalog,它具有atttypmod字段),因此无法仅通过typmod来区分两个功能。

据我所知,唯一的解决方法是创建一个domain(一个内置了typmod的用户定义类型别名)。这使您的函数可以引用typmod,而不必实际将它们存储在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更有意义,但是根据域来定义模式具有其自身的优势。)