将枚举不可变地转换为字符串

Mar*_*ery 5 postgresql

在 PostgreSQL 中将枚举值转换为字符串的正常方法是对其进行强制转换(使用::text),或者在将其连接到另一个字符串时简单地依赖隐式转换:

testdb=# CREATE TYPE color AS ENUM ('red', 'green', 'blue');
CREATE TYPE
testdb=# CREATE TABLE object (id serial, name text, color color);
CREATE TABLE
testdb=# INSERT INTO object (name, color) VALUES ('table', 'red'), ('chair', 'green');
INSERT 0 2
testdb=# SELECT name || color FROM object;
  ?column?  
------------
 tablered
 chairgreen
(2 rows)
Run Code Online (Sandbox Code Playgroud)

然而,有一个问题:Postgres似乎并不认为这种转换是不可变的。因此,如果您尝试在需要不可变表达式的地方(例如在列的定义中)使用它们,您会收到GENERATED错误

testdb=# ALTER TABLE object ADD COLUMN namecolor text GENERATED ALWAYS AS (name || color) STORED;
ERROR:  generation expression is not immutable
testdb=# ALTER TABLE object ADD COLUMN colorastext text GENERATED ALWAYS AS (color::text) STORED;
ERROR:  generation expression is not immutable
Run Code Online (Sandbox Code Playgroud)

这似乎不直观,而且不方便,因为我希望能够将枚举值连接到计算列中的字符串上。

因此,我有两个问题:

  1. 为什么 Postgres 考虑将枚举转换为字符串而不是不可变的?这种行为是一个错误吗?
  2. 是否有一种解决方法可以让我说服 Postgres 这样的转换是不可变的(并且有什么我应该警惕的风险)?

Lau*_*lbe 6

  1. 可以重命名枚举条目,因此转换不是IMMUTABLE.

  2. 如果您确定永远不会重命名枚举值,请编写自己的转换函数,在内部使用强制转换并将该函数标记为IMMUTABLE。那么 PostgreSQL 就会信任这个标签,而兑现承诺就取决于你了。