PostgreSQL - CAST vs :: operador na função da tabela LATERAL

Nov 27 2020

Enquanto eu 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
;

usando uma chamada explícita para CAST, eu não posso

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

usando o ::operador de chamada implicitamente :

ERROR: erro de sintaxe em ou próximo a "::"

Um outro local em que um explícito CASTé necessário:

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

Duvido que haja uma razão sintática, por exemplo, usar parênteses adicionais - que está incorreta aqui.

A chamada de função explícita é simplesmente necessária neste ponto como parte da implementação de baixo nível? Ou segue alguma regra de linguagem?

Respostas

5 ErwinBrandstetter Nov 27 2020 at 11:35

Excelentes exemplos de casos extremos. Ambas as variantes de sintaxe são "conversões de tipo explícitas", fazendo exatamente o mesmo. Acontece que alguns locais especiais no código SQL permitem apenas a notação funcional para evitar ambigüidades.

Quanto à sua segunda observação:

Um outro local em que um explícito CASTé necessário:

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

A sintaxe abreviada pode realmente ser usada aqui - com um conjunto adicional de parênteses para torná-la inequívoca:

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

db <> fiddle aqui

E qualquer variante de sintaxe corresponde à outra expressão nas consultas também. Vejo:

  • Podemos criar um índice para chave / valor do tipo de dados JSONB?
  • Como criar um índice em uma propriedade json inteira no postgres
  • Como dividir o Datetime em 2 colunas para o esquema de reserva do restaurante?

(Existem maneiras mais eficientes de fazer o que seu primeiro exemplo faz, mas isso provavelmente não vem ao caso.)

5 LaurenzAlbe Nov 27 2020 at 10:27

É um pouco estranho, sim, mas a gramática só aceitará algo sintaticamente semelhante a uma chamada de função em uma expressão function-in-FROM.

Portanto, esse é realmente um truque que você pode usar se quiser uma expressão arbitrária em uma FROMcláusula: envolva-a com uma CASTexpressão desnecessária .

O PostgreSQL tratará alegremente qualquer coisa que se pareça com uma função como uma função de tabela em tal contexto.