PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Index auf Timestamp:Funktionen im Indexausdruck müssen als IMMUTABLE gekennzeichnet sein

Zuerst dachte ich, das könnte ein Fehler im CREATE INDEX sein Logik. Aber der Punkt ist, dass die Umwandlung von text zu timestamptz selbst ist nicht IMMUTABLE entweder. Es hängt von flüchtigen Einstellungen wie datestyle ab .

In Ihrem speziellen Fall gibt es eine Problemumgehung, die noch besser ist als das, was Sie versucht haben. Verschieben Sie die Umwandlung in die Funktion:

CREATE OR REPLACE FUNCTION to_text(text) 
  RETURNS text AS
$func$
SELECT to_char($1::timestamptz AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
$func$ LANGUAGE sql IMMUTABLE;

Genauso effizient, aber jetzt CREATE INDEX kotzt nicht:

CREATE INDEX bar ON foo(to_text(j->>'start_time'));

Natürlich müssen Sie Ihre Funktionsaufrufe entsprechend anpassen:Lassen Sie den Cast ::timestamptz weg aus dem Ausdruck. Stellen Sie sicher, dass Sie überall dieselben Einstellungen verwenden , oder der Index könnte zu falschen Ergebnissen führen.

Noch besser

Verwenden Sie einen tatsächlich unveränderlichen Ausdruck mit to_timestamp() anstelle des Casts (sofern Ihr Eingabemuster dies zulässt):

CREATE OR REPLACE FUNCTION to_text(text) 
  RETURNS text AS
$func$
SELECT to_char(to_timestamp($1, 'YYYY-MM-DD"T"HH24:MI:SS.US')  -- adapt to your pattern
            AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US') 
$func$ LANGUAGE sql IMMUTABLE;

Beachten Sie jedoch (Zitat einer Fehlermeldung aus meinem Test):

Formatmuster "TZ"/"tz"/"OF" werden in to_date

nicht unterstützt