Enum unveränderlich in String umwandeln

Oct 04 2020

Die normale Methode zum Konvertieren eines Enum-Werts in eine Zeichenfolge in PostgreSQL besteht darin, ihn (mit ::text) umzuwandeln oder sich einfach auf die implizite Konvertierung zu verlassen, wenn Sie ihn beispielsweise in eine andere Zeichenfolge verketten:

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)

Es gibt jedoch einen Haken: Solche Conversions scheinen von Postgres nicht als unveränderlich angesehen zu werden. Infolgedessen wird eine Fehlermeldung angezeigt, wenn Sie versuchen, sie an einer Stelle zu verwenden, an der ein unveränderlicher Ausdruck erwartet wird, z. B. bei der Definition einer GENERATEDSpalte :

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

Dies scheint nicht intuitiv zu sein und ist unpraktisch, da ich in der Lage sein möchte, Aufzählungswerte auf Zeichenfolgen in einer berechneten Spalte zu verketten.

Somit habe ich zwei Fragen:

  1. Warum betrachtet Postgres die Konvertierung einer Aufzählung in eine Zeichenfolge als nicht unveränderlich? Ist dieses Verhalten ein Fehler?
  2. Gibt es eine Problemumgehung, mit der ich Postgres davon überzeugen kann, dass eine solche Konvertierung unveränderlich ist (und gibt es Risiken, vor denen ich vorsichtig sein sollte)?

Antworten

2 LaurenzAlbe Oct 05 2020 at 12:46
  1. Es ist möglich, einen Enum-Eintrag umzubenennen, die Besetzung jedoch nicht IMMUTABLE.

  2. Wenn Sie sicher sind, dass Sie Enum-Werte niemals umbenennen werden, schreiben Sie Ihre eigene Konvertierungsfunktion, die intern eine Umwandlung verwendet, und beschriften Sie die Funktion IMMUTABLE. Dann wird PostgreSQL diesem Label vertrauen und es liegt an Ihnen, das Versprechen zu erfüllen.