Os tipos de dados do PostgreSQL podem ser divididos em tipos de dados base, e tipos de dados contenedores [113], domínios e pseudo-tipos.
Os tipos de dados base são aqueles, como integer,
implementados abaixo do nível da linguagem SQL
(normalmente em uma linguagem de baixo nível, como C).
Correspondem geralmente ao que se chama de tipos de dados abstratos.
O PostgreSQL só pode operar nesses tipos
de dados por meio de funções fornecidas pelo usuário, e só entende o
comportamento desses tipos de dados à medida que os usuários os descrevem.
Os tipos de dados base nativos estão descritos em Tipos de dados.
Os tipos de dados enumerados (enum) podem ser
considerados uma subcategoria dos tipos de dados base.
A principal diferença é poderem ser criados usando apenas comandos
SQL, sem nenhuma programação de baixo nível.
Veja Tipos de dados de enumeração para obter mais informações.
O PostgreSQL possui três tipos de dados “contenedores”, que são tipos de dados que contêm vários valores de outros tipos de dados: são os tipos de dados matriz, composto e intervalo.
As matrizes podem conter vários valores que são todos do mesmo tipo de dados. Um tipo de dados matriz é criado automaticamente para cada tipo de dados base, tipo de dados composto, tipo de dados intervalo e tipo de dados de domínio. Mas não há matrizes de matrizes. No que diz respeito ao sistema de tipos de dados, as matrizes multidimensionais são iguais às matrizes unidimensionais. Veja Tipos de dados matriz para obter mais informações.
Os tipos de dados compostos, ou tipos de dados linha, são criados sempre que o usuário cria uma tabela. Também é possível usar CREATE TYPE para definir um tipo de dados composto “autônomo” (stand-alone) sem tabela associada. Um tipo de dados composto é apenas uma lista de tipos de dados com nomes de campos associados. Um valor do tipo de dados composto é uma linha ou registro de valores de campo. Veja Tipos de dados compostos para obter mais informações.
O tipo de dados intervalo pode conter dois valores do mesmo tipo de dados, que são os limites inferior e superior do intervalo. Os tipos de dados intervalo são criados pelo usuário, embora existam alguns nativos. Veja Tipos de dados de intervalo para obter mais informações.
Um domínio é baseado em um tipo de dados subjacente específico e, para muitos propósitos, é intercambiável com seu tipo de dados subjacente. Entretanto, um domínio pode ter restrições que limitam seus valores válidos a um subconjunto do que o tipo de dados subjacente permite. Os domínios são criados usando o comando SQL CREATE DOMAIN. Veja Tipos de dados de domínio para obter mais informações.
Existem alguns “pseudo-tipos” para propósitos especiais. Pseudotipos não podem aparecer como colunas de tabelas, ou componentes de tipos de dados contenedores, mas podem ser usados para declarar tipos de dados de argumento e resultado de funções. Isso fornece um mecanismo dentro do sistema de tipos de dados para identificar classes especiais de funções. A Tabela 8.27 lista os pseudo-tipos existentes.
Alguns pseudo-tipos de dados de interesse especial são os tipos de dados polimórficos [114], usados para declarar funções polimórficas. Esse poderoso recurso permite que uma única definição de função opere em muitos tipos de dados diferentes, com os tipos de dados específicos sendo determinado pelos tipos de dados realmente passados para a função em uma determinada chamada. Os tipos de dados polimórficos são mostrados na Tabela 36.1. Alguns exemplos de uso são mostrados em Funções SQL polimórficas.
Tabela 36.1. Tipos de dados polimórficos
| Nome | Família | Descrição |
|---|---|---|
anyelement | Simples | Indica que a função aceita qualquer tipo de dados |
anyarray | Simples | Indica que a função aceita qualquer tipo de dados matriz |
anynonarray | Simples | Indica que a função aceita qualquer tipo de dados não matriz |
anyenum | Simples | Indica que a função aceita qualquer tipo de dados enum (veja Tipos de dados de enumeração) |
anyrange | Simples | Indica que a função aceita qualquer tipo de dados intervalo (veja Tipos de dados de intervalo) |
anymultirange | Simples | Indica que a função aceita qualquer tipo de dados multi-intervalo (veja Tipos de dados de intervalo) |
anycompatible | Comum | Indica que a função aceita qualquer tipo de dados, com promoção automática dos vários argumentos para um tipo de dados comum |
anycompatiblearray | Comum | Indica que a função aceita qualquer tipo de dados matriz, com promoção automática dos vários argumentos para um tipo de dados comum |
anycompatiblenonarray | Comum | Indica que a função aceita qualquer tipo de dados não matriz, com promoção automática dos vários argumentos para um tipo de dados comum |
anycompatiblerange | Comum | Indica que a função aceita qualquer tipo de dados intervalo, com promoção automática dos vários argumentos para um tipo de dados comum |
anycompatiblemultirange | Comum | Indica que a função aceita qualquer tipo de dados multi-intervalo, com promoção automática dos vários argumentos para um tipo de dados comum |
Os argumentos e resultados polimórficos são vinculados entre si, sendo resolvidos para os tipos de dados específicos quando a consulta que chama a função polimórfica é analisada. Quando há mais de um argumento polimórfico, os tipos de dados reais dos valores de entrada devem corresponder conforme descrito abaixo. Se o tipo de dados do resultado da função for polimórfico, ou tiver parâmetros de saída de tipos de dados polimórficos, os tipos de dados desses resultados serão deduzidos dos tipos de dados reais das entradas polimórficas, conforme descrito abaixo.
Para os tipos de dados polimórficos da família “simples”, as regras de correspondência e dedução funcionam assim:
Cada posição (argumento ou valor retornado) declarada como
anyelement pode receber qualquer tipo de dados real,
mas em uma determinada chamada da função, todos devem ser do
mesmo tipo de dados real.
Cada posição declarada como anyarray pode receber
qualquer tipo de dados matriz, mas, da mesma forma, todos devem
ser do mesmo tipo de dados.
Da mesma forma, as posições declaradas como anyrange
devem ser todas do mesmo tipo de dados intervalo.
Da mesma forma para anymultirange.
Além disso, havendo posições declaradas como anyarray,
e outras declaradas como anyelement, o tipo de dados
real matriz nas posições anyarray deve ser uma matriz
cujos elementos são do mesmo tipo de dados aparecendo nas posições
de anyelement.
O tipo de dados anynonarray é tratado exatamente da
mesma forma que anyelement, mas adiciona a restrição
extra de que o tipo de dados real não deve ser um tipo de dados matriz.
O tipo de dados anyenum é tratado exatamente da mesma
forma que anyelement, mas adiciona a restrição extra
de que o tipo de dados real deve ser um tipo de dados enum.
Da mesma forma, havendo posições declaradas como anyrange,
e outras declaradas como anyelement ou anyarray,
o tipo de dados real intervalo nas posições anyrange
devem ser um intervalo cujo subtipo de dados é do mesmo tipo de dados
aparecendo nas posições anyelement, e idêntico ao
tipo de dados de elemento das posições anyarray.
Havendo posições declaradas como anymultirange, seu
tipo de dados real multi-intervalo deve conter intervalos
correspondentes aos parâmetros declarados como anyrange,
e elementos base correspondentes aos parâmetros declarados como
anyelement e anyarray.
Assim, quando mais de uma posição de argumento é declarada com um
tipo de dados polimórfico, o efeito líquido é que apenas certas
combinações de tipos de dados reais de argumentos são permitidas.
Por exemplo, uma função declarada como
equal(anyelement, anyelement) recebe quaisquer
dois valores de entrada, desde que sejam do mesmo tipo de dados.
Quando o valor retornado por uma função é declarado como de
tipo de dados polimórfico, deve haver pelo menos uma posição de
argumento que também seja polimórfica, e os tipos de dados reais
fornecidos para os argumentos polimórficos determinam o
tipo de dados real de resultado para essa chamada.
Por exemplo, se ainda não existisse um mecanismo de índice de
matriz, seria possível definir uma função que implementasse o
índice como
indice(anyarray, integer) returns anyelement.
Essa declaração restringe o primeiro argumento real a ser do tipo
de dados matriz, permitindo que o analisador infira o tipo de dados
do resultado correto a partir do tipo de dados do primeiro argumento
real.
Outro exemplo é que uma função declarada como
f(anyarray) returns anyenum
aceita apenas matrizes de tipos de dados enum.
Geralmente, o analisador pode inferir o tipo de dados real
para um tipo de resultado polimórfico a partir de argumentos que
são de um tipo de dados polimórfico diferente da mesma família;
por exemplo, anyarray pode ser deduzido de
anyelement, ou vice-versa.
Uma exceção é que um resultado polimórfico do tipo de dados
anyrange requer um argumento do tipo de dados
anyrange; não pode ser deduzido de argumentos
anyarray ou anyelement.
Isso acontece, porque pode haver vários tipos de dados intervalo
com o mesmo subtipo de dados.
Note que anynonarray e anyenum não
representam tipos de dados separados de variáveis; são do mesmo
tipo de dados que anyelement, apenas com uma restrição
adicional.
Por exemplo, declarar uma função como
f(anyelement, anyenum) equivale a
declará-la como f(anyenum, anyenum):
os dois argumentos reais devem ser do mesmo tipo de dados enum.
Para a família de tipos de dados polimórficos “comum”,
as regras de correspondência e dedução funcionam aproximadamente
da mesma forma que para a família “simples”,
com uma grande diferença:
os tipos de dados reais dos argumentos não precisam ser idênticos,
desde que possam ser convertidos implicitamente em um único
tipo de dados comum.
O tipo de dados comum é selecionado seguindo as mesmas regras de
UNION e construções relacionadas
(veja UNION, CASE e construções relacionadas).
A seleção do tipo de dados comum considera os tipos de dados reais de
entrada anycompatible e anycompatiblenonarray,
os tipos de dados de elemento matriz de entradas
anycompatiblearray, os subtipos de dados intervalo de
entradas anycompatiblerange, e os subtipos de dados
multi-intervalo de entradas anycompatiblemultirange.
Se anycompatiblenonarray estiver presente, o
tipo de dados comum deverá ser um tipo de dados não-matriz.
Depois que o tipo de dados comum é identificado, os argumentos nas
posições anycompatible e anycompatiblenonarray
são convertidos automaticamente para esse tipo de dados, e os argumentos
nas posições anycompatiblearray são convertidos
automaticamente para o tipo de dados matriz para esse tipo de dados.
Como não há como selecionar o tipo de dados intervalo sabendo apenas
seu subtipo de dados, o uso de anycompatiblerange e/ou
anycompatiblemultirange requer que todos os argumentos
declarados com esse tipo de dados tenham o mesmo intervalo real e/ou
tipo de dados multi-intervalo, e que o subtipo de dados desse
tipo de dados concorde com o tipo de dados comum selecionado, de modo
que nenhuma conversão dos valores de intervalo seja necessária.
Assim como em anyrange e anymultirange,
o uso de anycompatiblerange e anymultirange
como tipo de dados de resultado da função requer que exista um argumento
anycompatiblerange ou anycompatiblemultirange.
Note não haver nenhum tipo de dados anycompatibleenum.
Esse tipo de dados não seria muito útil, porque normalmente não há
conversões implícitas para tipos de dados enum, significando que
não haveria como resolver um tipo de dados comum para entradas enum
diferentes.
As famílias polimórficas “simples” e “comum” representam dois conjuntos independentes de tipos de dados de variáveis. Considere por exemplo
CREATE FUNCTION myfunc(a anyelement, b anyelement,
c anycompatible, d anycompatible)
RETURNS anycompatible AS ...
Em uma chamada real dessa função, as duas primeiras entradas devem ter o mesmo tipo de dados. As duas últimas entradas devem ser promovidas para um tipo de dados comum, mas esse tipo de dados não precisa ter nada a ver com o tipo de dados das duas primeiras entradas. O resultado terá o tipo de dados comum das duas últimas entradas.
Uma função variádica (aquela que recebe um número variável de
argumentos, como em Funções SQL com número variável de argumentos),
pode ser polimórfica:
isso é feito declarando seu último parâmetro como
VARIADIC anyarray ou
VARIADIC anycompatiblearray.
Para fins de correspondência de argumentos e determinação do tipo
de dados de resultado real, essa função se comporta da mesma forma
como se tivesse sido escrito o número apropriado de parâmetros
anynonarray ou anycompatiblenonarray.
[113] Neologismos usados: contenedor (espanhol), variádica (do inglês variadic) (N. T.)
[114] Polimórfico: relativo à polimorfia, qualidade ou condição do que está sujeito à mudar de forma ou do que se apresenta sob diversas formas: desenho polimórfico, plástico polimórfico. Dicio, Dicionário Online de Português (N. T.)