PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Indice su Timestamp:le funzioni nell'espressione dell'indice devono essere contrassegnate come IMMUTABLE

Per prima cosa ho pensato che questo potesse essere un bug in CREATE INDEX logica. Ma il punto è che il cast di text a timestamptz di per sé non è IMMUTABLE o. Dipende da impostazioni volatili come datestyle .

Nel tuo caso particolare c'è una soluzione alternativa che è persino migliore di quella che hai provato. Sposta il cast nella funzione:

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;

Altrettanto efficiente, ma ora CREATE INDEX non vomita:

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

Ovviamente, devi regolare le tue chiamate di funzione di conseguenza:elimina il cast ::timestamptz dall'espressione. Assicurati di utilizzare le stesse impostazioni ovunque o l'indice potrebbe portare a risultati falsi.

Meglio ancora

Usa un'espressione effettivamente immutabile con to_timestamp() invece del cast (se il tuo modello di input lo consente):

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;

Nota tuttavia (citando un messaggio di errore dal mio test):

I modelli di formato "TZ"/"tz"/"OF" non sono supportati in to_date