A seguinte consulta com função não determinística produz duas mesmas linhas - o CTE é calculado e reutilizado.
WITH foo AS (SELECT uuid_generate_v4() AS id)
SELECT id FROM foo
UNION ALL
SELECT id FROM foo
| id
| 741f4f69-416b-4b4c-9226-559527f4a84e
| 741f4f69-416b-4b4c-9226-559527f4a84e
Essa execução é garantida? O postgres pode decidir inline-lo para
SELECT id FROM (SELECT uuid_generate_v4() AS id) t
UNION ALL
SELECT id FROM (SELECT uuid_generate_v4() AS id) t
| id
| 262f0006-b4d5-440a-a86a-d79cd2684458
| c24b5835-9c5c-4d6f-b649-8e510129015b
que produz dois ids diferentes (e, portanto, resultados diferentes)?
O que o padrão SQL especifica? O Postgres oferece alguma garantia adicional? Se não for garantido, qual é a maneira padrão de reutilizar a instrução que depende de procedimentos não determinísticos?
Sim, esta execução garantida. O Postgres não irá inline-lo da maneira que você mencionou.
O padrão SQL não define o comportamento nesses casos, ficando a cargo da implementação de servidores SQL. Ele (rascunho de 2013 de qualquer maneira) diz, em particular, na seção 7.6 <referência da tabela>
onde <nome da consulta> é o que é definido pela
WITH
cláusula, enquanto em 4.22 Determinismo menciona:Seção 4.15.8 A análise sintática de tabelas derivadas e cursores pode ser interpretada para significar que cada referência a
uuid_generate_v4()
no seu caso produzirá um nó distinto na árvore sintática. Se o otimizador de um determinado DBMS escolhe honrar sua natureza não determinística e executar a função duas vezes é específico da implementação.