PostgreSQL中的函数调用行为不正常

时间:2018-03-06 10:59:51

标签: postgresql function arguments call

我使用PostgreSQL 10.3。

我创建了以下域名:

CREATE DOMAIN common.citext_nullable
    AS extensions.citext;

CREATE DOMAIN common.citext_not_null
    AS extensions.citext NOT NULL;

CREATE DOMAIN common.smallint_ge_zero_nullable
    AS smallint;

ALTER DOMAIN common.smallint_ge_zero_nullable
    ADD CONSTRAINT smallint_ge_zero_nullable_check CHECK (value >= 0);

以及以下功能:

CREATE OR REPLACE FUNCTION common.fun_name(
        p_1    common.citext_not_null,
        p_2    common.citext_nullable,
        p_3    common.citext_nullable,
        p_4    common.smallint_ge_zero_nullable)
    RETURNS ...
    LANGUAGE 'plpgsql'
AS $BODY$
    DECLARE
        ...
    BEGIN
    ...
    END;
$BODY$;

注意:

  1. 所有参数/参数均为类型。
  2. 域和功能属于同一模式"常见"。
  3. 架构"常见"包含在搜索路径中。
  4. 所有扩展程序都在架构"扩展程序"。
  5. 架构"扩展"也包括在搜索路径中。
  6. " citext" -based domains按预期工作。
  7. "基于smallint"的域名工作奇怪。
  8. 上述域名和功能在问题范围内进行了简化。
  9. 我可以通过

    调用该函数
    SELECT fun_name('any', 'any', 'any', 5::smallint_ge_zero_nullable);
    

    甚至

    SELECT fun_name('any', 'any', 'any', '5');
    

    但我无法通过以下方式来称呼它:

    SELECT fun_name('any', 'any', 'any', 5);
    

    我收到以下错误:

    SQL Error [42883]: ERROR: function fun_name(unknown, unknown, unknown, integer) does not exist
      Hint: No function matches the given name and argument types. You might need to add explicit type casts.
      Position: 8
    

    为什么"基于citext"的参数显示为"未知"?根据文档,第1431页

      

    argtype

         

    函数参数的数据类型(可选择模式限定),如果有的话。参数类型可以是基本类型,复合类型或域类型,或者......

    ("有趣"" 未知"参数最终被接受并按预期工作," 整数"参数不被接受,行为异常。)

1 个答案:

答案 0 :(得分:1)

此行为与int - smallint转换有关,而与域无关。

您可以找到将函数调用与函数关联的规则here。它将在可用时使用隐式转换,并始终将“未知”类型与任何内容匹配。由于您的函数只有一个签名,因此案例1(显式转换)和2(所有未知)将与您的函数匹配。

没有自动向下转换,所以整数 - > smallInt不会隐含地发生。让我们考虑一个具有两个签名f(input as int)f(input as smallint)的函数。如果要进行向下转换,在调用f(5)时应该使用哪一个?此邮件列表thread将提供更多详细信息。

所以解决方案要么是 - 进行明确的铸造(案例1)
- 或者有一个函数包装器,其中包含为您执行转换的泛型类型(整数)(并处理错误..) - 或者使用具有正确类型的表列的输出调用该函数。