能否在不使用C语言编写函数的情况下在PostgreSQL中创建自定义类型?

4

我试图创建一种类型,以字节形式存储颜色十六进制。我按照postgres文档中的所有说明进行操作,网址是:http://www.postgresql.org/docs/9.3/static/sql-createtype.html,在其中找到了这部分: CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ; 但是省略号里该填写什么让我感到有些不安。结果证明,我的不安是有道理的,因为我无法找到任何在不使用C语言自定义PG函数的情况下创建简单数据类型的示例。
我最好的尝试是:

CREATE TYPE color;
CREATE FUNCTION color_in(cstring) RETURNS color AS $$
    BEGIN
        RETURN decode($1::text, 'hex')::color;
    END;
$$ LANGUAGE PLPGSQL IMMUTABLE RETURNS NULL ON NULL INPUT;
CREATE FUNCTION color_out(color) RETURNS cstring AS $$
    BEGIN
        RETURN encode($1::bytea, 'hex')::text;
    END;
$$ LANGUAGE PLPGSQL IMMUTABLE RETURNS NULL ON NULL INPUT;

CREATE TYPE color (
    INTERNALLENGTH = 3,
    LIKE = bytea,
    INPUT = color_in,
    OUTPUT = color_out
);

这会导致错误:
NOTICE:  return type color is only a shell
ERROR:  PL/pgSQL functions cannot return type color

如果我使用语言SQL或默认为SPL,会出现类似的错误。这里列出了示例输入输出函数:http://www.postgresql.org/docs/9.3/static/xtypes.html。唯一的示例函数是用C编写的。我正确地认为这是在postgres中编写UDT的唯一方法吗?还有其他方法吗?我的目标是将颜色存储为字节,但其本机文本形式应为十六进制(用于转储、恢复和从原始数据进行转换)。

你觉得把定义放在代码块的底部不如放在顶部吗? - Politank-Z
@Politank:不行,它会抱怨color_in不存在。 - Nick Barnes
1
FYI,Postgres的开发人员之一写了一份关于用户定义类型的详细教程,并以24位RGB颜色作为示例。现在你只需要编译它即可。 - Nick Barnes
1个回答

3

来自http://www.postgresql.org/docs/9.4/interactive/datatype-pseudo.html

用过程语言编写的函数只能按照其实现语言允许使用伪类型。目前,过程语言都禁止将伪类型用作参数类型,并仅允许 void 和 record 作为结果类型(当函数用作触发器时还包括 trigger)。一些过程语言也支持使用 anyelement、anyarray、anynonarray、anyenum 和 anyrange 类型的多态函数。

以及来自http://www.postgresql.org/docs/9.4/interactive/sql-createtype.html

输入函数可以声明为接受一个 cstring 类型的参数,或者声明为接受三个参数,分别为 cstring、oid 和 integer 类型。

输出函数必须返回 cstring 类型。

根据以上内容:

  1. 基本数据类型的输入和输出函数使用 cstring。
  2. 过程语言不能使用 cstring。
  3. 基本数据类型函数不能用过程语言编写。
  4. 纯粹使用过程语言无法定义基本数据类型。

您可以使用现有的输入和输出函数,但我认为没有一个直接可以得到十六进制字符串。最接近的可能是 \x 十六进制转义的 bytea,但您的文本表示中会有一个 \x。如果您愿意进行文本转换,我认为您可以使用 bytea_in 和 bytea_out 创建一个类型,并编写自定义转换以进行文本转换。但您必须显式地进行强制转换以避免出现 \x。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接