Recentemente descobri um comportamento do PostgreSQL que é estranho e problemático na minha opinião.
Considere esta consulta simples
SELECT
'something confidential'
WHERE FALSE;
A cláusula sem sentido WHERE FALSE
se assemelha aqui a uma verificação de permissão muito estrita. Isso funciona como esperado: nada é retornado.
Agora, imagine que você adiciona uma coluna adicional, por exemplo, uma count
função. Isso dá é esta consulta:
SELECT
'something confidential'
,count(CURRENT_DATE)
WHERE FALSE;
(O parâmetro de count
poderia ser qualquer coisa. CURRENT_DATE
é apenas um exemplo aleatório.)
Agora, obtemos
algo confidencial | 0
Eu acho que isso é de alguma forma de propósito, no sentido de que SELECT count(CURRENT_DATE);
retorna 1 se a condição for verdadeira e 0 se a condição for falsa.
No entanto, considero isso problemático em situações em que você não está ciente disso. Então, minhas perguntas são
- Por quê? Qual é o pano de fundo desse comportamento?
- Como posso fazer essa consulta retornar zero linhas em vez de uma linha com valor 0 para
count
? - Existe uma maneira direta na consulta para evitar o retorno acidental de linhas que você não deseja retornar adicionando funções de agregação? (Ou seja, além de testes externos, etc.)
Estou usando o PostgreSQL 12.1, mas o comportamento é o mesmo para versões mais antigas.
Esse é o comportamento padrão do SQL para praticamente todos os bancos de dados.
Existem três maneiras de como as linhas são retornadas:
Em outras palavras, agregar sem agrupar se comporta como se houvesse um único grupo, ou seja, como se você tivesse escrito
GROUP BY ()
(uma cláusula GROUP BY com uma lista vazia resulta em um único grupo 'do nada', semelhante a como uma consulta sem resultados FROM em uma única linha 'do nada').Para evitar o retorno desta linha de grupo único, você pode
adicione um GROUP BY explícito, para que você termine no caso 3. acima (depois de WHERE filtrar todas as linhas, não há valor a partir do qual um grupo possa ser criado):
mova a agregação para uma subconsulta, para que a verificação de permissão afete a saída disso:
mova a verificação de permissão para a cláusula HAVING (se isso for possível), para que a saída para o único grupo seja descartada:
Este é o comportamento esperado (não apenas para Postgres). Se observarmos a ordem lógica de avaliação de uma consulta:
Vou adicionar uma tabela (T) com uma coluna (x) e uma linha no exemplo
Nós temos:
O resultado é uma linha com valor 0. Em seguida, adicionamos uma constante 'algo confidencial' a essa linha e terminamos com: