可以在 postgres 中创建自定义类型而不用 C 编写函数吗?

Joc*_*ken 5 postgresql postgresql-9.3

我正在尝试创建一种类型来存储颜色十六进制,最好以字节形式存储。我按照 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
);
Run Code Online (Sandbox Code Playgroud)

这会产生错误:

NOTICE:  return type color is only a shell
ERROR:  PL/pgSQL functions cannot return type color
Run Code Online (Sandbox Code Playgroud)

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

use*_*502 3

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

用过程语言编码的函数只能在其实现语言允许的情况下使用伪类型。目前过程语言都禁止使用伪类型作为参数类型,只允许使用void和record作为结果类型(当函数作为触发器时还可以使用触发器)。有些还支持使用类型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 。