A linguagem SQL é fortemente tipada, ou seja, cada item de dados tem um tipo de dados associado que determina o seu comportamento e o uso permitido. O PostgreSQL possui um sistema extensível de tipos de dados, mais geral e flexível que o encontrado em outras implementações da linguagem SQL. Portanto, a maior parte do comportamento de conversão de tipo de dados no PostgreSQL é governado por regras gerais, e não por heurísticas ad hoc. Isso permite o uso de expressões com tipos de dados diversos, mesmo com tipos de dados definidos pelo usuário.
O rastreador/analisador (scanner/parser) do PostgreSQL divide os elementos léxicos em cinco categorias fundamentais: números inteiros, números não inteiros, cadeias de caracteres, identificadores e palavras-chave. As constantes da maioria dos tipos de dados não numéricos são primeiramente classificadas como cadeia de caracteres. A definição da linguagem SQL permite especificar nomes de tipo de dados usando cadeia de caracteres, e esse mecanismo pode ser usado no PostgreSQL para iniciar o analisador no caminho correto. Por exemplo, a consulta
SELECT text 'Origin' AS "label", point '(0,0)' AS "value";
label | value --------+------- Origin | (0,0) (1 linha)
possui duas constantes literais, dos tipos de dados text e
point. Se não for especificado o tipo de dados para um literal
cadeia de caracteres, será atribuído inicialmente o tipo de dados provisório
unknown, para ser resolvido em estágios posteriores,
conforme descrito abaixo.
Existem quatro construções SQL fundamentais que requerem regras de conversão de tipo de dados distintas no analisador do PostgreSQL:
Grande parte do sistema de tipos de dados do PostgreSQL é construído em torno de um rico conjunto de funções. As funções podem ter um ou mais argumentos. Como o PostgreSQL permite sobrecarga (overload) de função, o nome da função sozinho não identifica unicamente a função a ser chamada; o analisador deve selecionar a função correta segundo os tipos de dados dos argumentos fornecidos.
O PostgreSQL permite expressões com operadores de prefixo (um argumento), bem como operadores infixos (dois argumentos). Assim como as funções, os operadores podem ser sobrecarregados, de modo que existe o mesmo problema para selecionar o operador correto.
As instruções SQL INSERT e
UPDATE colocam os resultados das expressões em uma
tabela. As expressões na instrução devem corresponder, e talvez serem
convertidas, para os tipos de dados das colunas de destino.
UNION, CASE, e relacionadas
Como os resultados de todas as instruções SELECT
de uma construção UNION devem retornar em um único
conjunto de colunas, os tipos de dados dos resultados das instruções
SELECT envolvidas devem corresponder e produzirem
um conjunto uniforme de saída.
Da mesma maneira, as expressões de resultado de uma construção
CASE devem ser convertidas em um tipo de dados comum,
para que a expressão CASE tenha um
tipo de dados de saída conhecido.
Algumas outras construções, como ARRAY[] e as funções
GREATEST e LEAST, também
requerem a determinação de um tipo de dados comum para várias subexpressões.
Os catálogos do sistema armazenam informações sobre quais conversões, ou casts, existem entre quais tipos de dados e como realizar estas conversões. Podem ser criadas conversões adicionais pelo usuário usando o comando CREATE CAST. (Isto é geralmente feito em conjunto com a definição de novos tipos de dados. O conjunto de conversões entre os tipos de dados nativos foi cuidadosamente elaborado, sendo melhor não alterá-lo.)
Uma heurística adicional fornecida pelo analisador permite uma melhor
determinação do comportamento de conversão adequado entre grupos de
tipos de dados que possuem conversões implícitas. Os tipos de dados são
divididos em várias categorias de tipo básicas,
incluindo boolean, numeric, string,
bitstring, datetime, timespan,
geometric, network e definido pelo usuário.
(Para obter a lista veja a Tabela 52.65;
mas observe que também é possível criar categorias de tipo de dados
personalizado.)
Dentro de cada categoria pode haver um ou mais
tipos preferidos, que são os preferidos quando há
uma escolha de tipos de dados possíveis.
Com a seleção cuidadosa de tipos de dados preferidos e conversões
implícitas disponíveis, é possível garantir que expressões ambíguas
(aquelas com várias soluções de análise candidatas) possam ser
resolvidas de uma forma útil.
Todas as regras de conversão de tipo de dados são projetadas com vários princípios em mente:
As conversões implícitas nunca devem ter resultados surpreendentes ou imprevisíveis.
Não deve haver sobrecarga adicional no analisador ou executor, se uma consulta não precisar de conversão de tipo de dados implícita. Ou seja, se uma consulta for bem formada e os tipos de dados já corresponderem, a consulta deverá ser executada sem gastar tempo adicional do analisador, e sem introduzir chamadas de conversão implícitas desnecessárias na consulta.
Além disso, se uma consulta requer geralmente a conversão implícita para uma função, e se o usuário definir uma nova função com os tipos de dados de argumentos corretos, o analisador deverá usar esta nova função, e não mais fazer a conversão implícita para usar a função antiga.