【问题标题】:How to write a custom struct data type for PostgreSQL using internal types如何使用内部类型为 PostgreSQL 编写自定义结构数据类型
【发布时间】:2017-07-05 00:21:34
【问题描述】:

我使用的是 PostgreSQL 9.6。我想在 PostgreSQL 上创建一个新的货币类型扩展,其中包含一个字符串和一个数值。

根据文档https://www.postgresql.org/docs/9.6/static/sql-createtype.html,我可以直接在 PostgreSQL 中使用 compose 类型,但这不是我想要的,因为我希望能够使用字符串来表示类型并进行强制转换。所以解决方案是创建一个自定义类型,例如示例“box”类型。文档显示:

CREATE TYPE box;

CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ;
CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ;

CREATE TYPE box (
   INTERNALLENGTH = 16,
   INPUT = my_box_in_function,
   OUTPUT = my_box_out_function
);

但是对于如何编写这样的函数并没有真正的帮助。进一步搜索显示该函数只能用 C 编写,并且显示的是简单类型的示例,而不是结构类型。

所以我基本上想要类似的东西

typedef struct {
    char code[4];
    Numeric  numeric;
} Currency

我想使用固定类型的 Numeric,这样可以避免实现 varlena 标头的额外工作。此外货币通常有固定的小数点。我还希望能够在内部使用 Numeric 类型,因为它允许我重用 Numeric 的功能。

如何使用 Numeric,以便可以使用与 PostgreSQL 类似的语法(例如 Numeric(10,2))来定义我的结构?我可以在 currency_in 函数中使用 numeric_in 函数吗?

【问题讨论】:

  • 我怀疑你实际上是想创建一个 Composite 类型,而不是 Base 类型。
  • 以这种方式做你想做的事是很多工作。您需要定义运算符、用于索引访问的运算符类等等。你需要对 postgres 的很​​多内容有深入的了解; C 语言中的用户定义数据类型的全面实现并非易事。考虑一个域或复合类型。
  • 事实上,按照你描述的方式去做是行不通的,因为 VARLENA 标题必须放在第一位。
  • @Kevin 是的,但是对于复合类型,我不能有自定义输出,也不能输入。我必须输入内容为 ('USD', 1) 而不是 'USD1'
  • @CraigRinger 但如果它是固定大小的数字类型,您是否需要 varlena 标头。那么整个货币类型也是固定大小的。

标签: c postgresql postgresql-extensions


【解决方案1】:

characternumeric 都是 varlena,因此您将无法将它们存储在固定长度的数据结构中。

我将数据类型定义为

typedef struct {
    /* value times 100 */
    int64 value;
    /* currency name */
    char denomination[4];
} currency;

最后存储字符可以避免对齐问题。

对值的操作现在是简单的整数操作。我不希望您要乘以或除两个 currency 值;这没有多大意义。

【讨论】:

  • 有趣的解决方案,是的,我查看了代码,似乎货币类型共享类似的实现(使用整数存储值)。
  • 您能详细介绍一下对齐问题吗?我听说过这个,但我不太熟悉。
  • this Wikipedia article。我说的话很草率;这更多的是浪费空间的问题。如果char 字段的长度为 4 个字节,则在某些平台上可能会因为填充而浪费 4 个字节。
猜你喜欢
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多