Os comandos SQL podem, intencionalmente ou não, usar tipos de dado diferentes na mesma expressão. O PostgreSQL possui muitas funcionalidades para processar expressões com mistura de tipos.
Em muitos casos não há necessidade do usuário compreender os detalhes do mecanismo de conversão de tipo. Entretanto, as conversões implícitas feitas pelo PostgreSQL podem afetar o resultado do comando. Quando for necessário, os resultados podem ser personalizados utilizando uma conversão de tipo explícita.
Este capítulo apresenta os mecanismos e as convenções de conversão de tipo de dado do PostgreSQL. Consulte as seções relevantes no Capítulo 8 e no Capítulo 9 para obter informações adicionais sobre tipos de dado específicos, e funções e operadores permitidos, respectivamente.
A linguagem SQL é uma linguagem fortemente tipada, ou seja, todo item de dado possui um tipo de dado associado que determina seu comportamento e a utilização permitida. O PostgreSQL possui um sistema de tipo de dado extensível, muito mais geral e flexível do que o de outras implementações do SQL. Por isso, a maior parte do comportamento de conversão de tipo de dado do PostgreSQL é governado por regras gerais, em vez de heurísticas [1] ad hoc [2] , permitindo, assim, expressões com tipos diferentes terem significado mesmo com tipos definidos pelo usuário.
O rastreador/analisador (scanner/parser) do PostgreSQL divide os elementos léxicos em apenas cinco categorias fundamentais: inteiros, números não inteiros, cadeias de caracteres, identificadores e palavras chave. As constantes dos tipos não numéricos são, em sua maioria, classificadas inicialmente como cadeias de caracteres. A definição da linguagem SQL permite especificar o nome do tipo juntamente com a cadeia de caracteres, e este mecanismo pode ser utilizado no PostgreSQL para colocar o analisador no caminho correto. Por exemplo, a consulta
=> SELECT text 'Origem' AS "local", point '(0,0)' AS "valor"; local | valor --------+------- Origem | (0,0) (1 linha)
possui duas constantes literais, dos tipos text e point. Se não for especificado um tipo para o literal cadeia de caracteres, então será atribuído inicialmente o tipo guardador de lugar unknown (desconhecido), a ser determinado posteriormente nos estágios descritos abaixo.
Existem quatro construções SQL fundamentais que requerem regras de conversão de tipo distintas no analisador do PostgreSQL:
Grande parte do sistema de tipo do PostgreSQL é construído em torno de um amplo conjunto de funções. As funções podem possuir um ou mais argumentos. Como o PostgreSQL permite a sobrecarga de funções, o nome da função, por si só, não identifica unicamente a função a ser chamada; o analisador deve selecionar a função correta baseando-se nos tipos de dado dos argumentos fornecidos.
O PostgreSQL permite expressões com operadores unários (um só argumento) de prefixo e de sufixo, assim como operadores binários (dois argumentos). Assim como as funções, os operadores podem ser sobrecarregados e, portanto, existe o mesmo problema para selecionar o operador correto.
Os comandos SQL INSERT e UPDATE colocam os resultados das expressões em tabelas. As expressões nestes comandos devem corresponder aos tipos de dado das colunas de destino, ou talvez serem convertidas para estes tipos de dado.
Como os resultados de todas as cláusulas SELECT de uma declaração envolvendo união devem aparecer em um único conjunto de colunas, deve ser feita a correspondência entre os tipos de dado dos resultados de todas as cláusulas SELECT e a conversão em um conjunto uniforme. Do mesmo modo, os resultados das expressões da construção CASE devem ser todos convertidos em um tipo de dado comum, para que a expressão CASE tenha, como um todo, um tipo de dado de saída conhecido. O mesmo se aplica às construções ARRAY.
Os catálogos do sistema armazenam informações sobre que conversões entre tipos de dado, chamadas de casts, são válidas, e como realizar estas conversões. Novas conversões podem ser adicionadas pelo usuário através do comando CREATE CAST (Geralmente isto é feito junto com a definição de novos tipos de dado. O conjunto de conversões entre os tipos nativos foi cuidadosamente elaborado, sendo melhor não alterá-lo).
É fornecida no analisador uma heurística adicional para permitir estimar melhor o comportamento apropriado para os tipos do padrão SQL. Existem diversas categorias de tipo básicas definidas: boolean, numeric, string, bitstring, datetime, timespan, geometric, network e a definida pelo usuário. Cada categoria, com exceção da definida pelo usuário, possui um ou mais tipo preferido, selecionado preferencialmente quando há ambigüidade. Na categoria definida pelo usuário, cada tipo é o seu próprio tipo preferido. As expressões ambíguas (àquelas com várias soluções de análise candidatas) geralmente podem, portanto, serem resolvidas quando existem vários tipos nativos possíveis, mas geram erro quando existem várias escolhas para tipos definidos pelo usuário.
Todas as regras de conversão de tipo foram projetadas com vários princípios em mente:
As conversões implícitas nunca devem produzir resultados surpreendentes ou imprevisíveis.
Tipos definidos pelo usuário, para os quais o analisador não possui nenhum conhecimento a priori, devem estar "acima" na hierarquia de tipo. Nas expressões com tipos mistos, os tipos nativos devem sempre ser convertidos no tipo definido pelo usuário (obviamente, apenas se a conversão for necessária).
Tipos definidos pelo usuário não se relacionam. Atualmente o PostgreSQL não dispõe de informações sobre o relacionamento entre tipos, além das heurísticas codificadas para os tipos nativos e relacionamentos implícitos baseado nas funções e conversões disponíveis.
Não deve haver nenhum trabalho extra do analisador ou do executor se o comando não necessitar de conversão de tipo implícita, ou seja, se o comando estiver bem formulado e os tipos já se correspondem, então o comando deve prosseguir sem despender tempo adicional no analisador, e sem introduzir chamadas de conversão implícita desnecessárias no comando.
Além disso, se o comando geralmente requer uma conversão implícita para a função, e se o usuário definir uma nova função com tipos corretos para os argumentos, então o analisador deve usar esta nova função, não fazendo mais a conversão implícita utilizando a função antiga.
[1] |
heurística — Rubrica: informática. — método de investigação baseado na aproximação progressiva de um dado problema. Dicionário Eletrônico Houaiss da língua portuguesa 1.0 (N. do T.) |
[2] |
ad hoc — destinado a essa finalidade; feito exclusivamente para explicar o fenômeno que descreve e que não serve para outros casos, não dando margem a qualquer generalização (diz-se de regra, argumento, definição etc.) — Dicionário Eletrônico Houaiss da língua portuguesa 1.0 (N. do T.) |