PostgreSQL: operatore CAST vs :: sulla funzione tabella LATERALE

Nov 27 2020

Finché posso

SELECT elem[1], elem[2]
FROM   ( VALUES ('1,2'::TEXT) ) AS q(arr),
       LATERAL CAST(String_To_Array(q.arr, ',') AS INT[]) AS elem
;

utilizzando una chiamata esplicita a CAST, non posso

SELECT elem[1], elem[2]
FROM   ( VALUES ('1,2'::TEXT) ) AS q(arr),
       LATERAL String_To_Array(q.arr, ',')::INT[] AS elem
;

utilizzando l' ::operatore chiamante implicitamente :

ERRORE: errore di sintassi in corrispondenza o vicino a "::"

Un'altra posizione in cui CASTè richiesto un esplicito :

CREATE INDEX ON ... ( CAST(<straw> AS <gold>) );

Dubito che ci sia una ragione sintattica, ad esempio l'uso di parentesi di chiusura extra - che qui non è corretto.

La chiamata di funzione esplicita è semplicemente necessaria a questo punto come parte dell'implementazione di basso livello? O segue delle regole linguistiche?

Risposte

5 ErwinBrandstetter Nov 27 2020 at 11:35

Esempi eccellenti di case d'angolo. Entrambe queste varianti di sintassi sono "cast di tipo esplicito", che fanno esattamente lo stesso. Accade così che alcune posizioni speciali nel codice SQL consentano solo la notazione funzionale per evitare ambiguità.

Per quanto riguarda la tua seconda osservazione:

Un'altra posizione in cui CASTè richiesto un esplicito :

CREATE INDEX ON ... ( CAST(<straw> AS <gold>) );

La sintassi abbreviata può essere effettivamente utilizzata qui, con un set aggiuntivo di parentesi per renderla univoca:

CREATE INDEX ON ... ((<straw>::<gold>));

db <> fiddle qui

Inoltre, entrambe le varianti di sintassi corrispondono anche all'altra espressione nelle query. Vedere:

  • Possiamo creare un indice per chiave / valore del tipo di dati JSONB?
  • Come creare un indice su una proprietà json intera in postgres
  • Dividere Datetime in 2 colonne per lo schema di prenotazione del ristorante?

(Ci sono modi più efficienti per fare ciò che fa il tuo primo esempio, ma probabilmente non è questo il punto.)

5 LaurenzAlbe Nov 27 2020 at 10:27

È un po 'strano, sì, ma la grammatica accetterà solo qualcosa di sintatticamente simile a una chiamata di funzione in un'espressione function-in-FROM.

Quindi questo è davvero un trucco che puoi usare se vuoi un'espressione arbitraria in una FROMclausola: circondala con CASTun'espressione non necessaria .

PostgreSQL tratterà felicemente tutto ciò che assomiglia a una funzione come una funzione di tabella in un tale contesto.