8.19. Tipos de dados de identificador de objeto #

Os identificadores de objeto (OIDs) são usados internamente pelo PostgreSQL como chaves primárias para várias tabelas do sistema. O tipo de dados oid representa um identificador de objeto. Existem também vários tipos de dados alias para oid, cada um chamado regalguma_coisa. A Tabela 8.26 mostra uma visão geral.

No momento, o tipo de dados oid é implementado como inteiro sem sinal de quatro bytes. Portanto, não é grande o suficiente para fornecer unicidade em todo o banco de dados em grandes bancos de dados, ou mesmo em grandes tabelas individualmente.

O próprio tipo de dados oid tem poucas operações além da de comparação. Entretanto, pode ser convertido em inteiro e depois tratado usando os operadores padrão para inteiros. (Cuidado com a possível confusão entre com sinal versus sem sinal, se isto for feito.)

Os tipos de dados alias de OID não têm operações próprias, exceto rotinas de entrada e saída especializadas. Estas rotinas conseguem aceitar e exibir nomes simbólicos para objetos do sistema, em vez do valor numérico bruto que o tipo de dados oid usaria. Os tipos de dados alias permitem a procura simplificada de valores de OID para objetos. Por exemplo, para examinar as linhas da tabela pg_attribute relacionadas a uma tabela minha_tabela, pode ser escrito:

SELECT *
    FROM pg_attribute
    WHERE attrelid = 'minha_tabela'::regclass;

em vez de:

SELECT * FROM pg_attribute
  WHERE attrelid =
      (SELECT oid
       FROM pg_class
       WHERE relname = 'minha_tabela');

Embora isto não pareça tão ruim por si só, ainda assim é simplificado demais. Seria necessária uma subconsulta muito mais complicada para selecionar o OID correto se houvesse várias tabelas chamadas minha_tabela em esquemas diferentes. O conversor de entrada regclass trata a procura de tabela segundo a configuração do caminho do esquema e, portanto faz a coisa certa automaticamente. Da mesma forma, converter o OID de uma tabela para o tipo de dados regclass é útil para a exibição simbólica de um OID numérico.

Tabela 8.26. Tipos de dados de identificador de objeto

NomeReferênciaDescriçãoExemplo de valor
oidtodosidentificador numérico de objeto564182
regclasspg_classnome da relaçãopg_type
regcollationpg_collationnome da ordenação"POSIX"
regconfigpg_ts_configconfiguração da procura de textoenglish
regdictionarypg_ts_dictdicionário de procura de textosimple
regnamespacepg_namespacenome do espaço de nomespg_catalog
regoperpg_operatornome do operador+
regoperatorpg_operatoroperador com os tipos de dados dos argumentos*(integer,​integer) ou -(NONE,​integer)
regprocpg_procnome da funçãosum
regprocedurepg_procfunção com os tipos de dados dos argumentossum(int4)
regrolepg_authidnome do papel (role)smithee
regtypepg_typenome do tipo de dadosinteger

Todos os tipos de dados alias de OID para objetos agrupados por espaço de nome aceitam nomes qualificados pelo esquema, e exibem nomes qualificados pelo esquema na saída, se o objeto não for encontrado no caminho de procura corrente sem ser qualificado. Por exemplo, meu_esquema.minha_tabela é uma entrada aceitável para regclass (se houver tal tabela). Esse valor pode ser gerado como meu_esquema.minha_tabela, ou apenas minha_tabela, dependendo do caminho de procura corrente. Os tipos de dados alias regproc e regoper só aceitam nomes de entrada únicos (não sobrecarregados), portanto são de uso limitado; para a maioria dos usos, regprocedure ou regoperator são mais apropriados. Para regoperator, os operadores unários são identificados escrevendo NONE para o operando não utilizado.

As funções de entrada para esses tipos de dados permitem espaços em branco entre os tokens, e transformam letras maiúsculas em minúsculas, exceto quando estão entre aspas; isto é feito para tornar as regras de sintaxe semelhantes à maneira como os nomes de objetos são escritos no SQL. Por outro lado, as funções de saída usam aspas, se necessário, para tornar a saída um identificador SQL válido. Por exemplo, o OID da função chamada Foo (com F maiúsculo) aceitando dois argumentos inteiros pode ser entrada como ' "Foo" ( int, integer ) '::regprocedure. A saída ficaria parecida com "Foo"(integer,integer). Tanto o nome da função quanto o nome do tipo de dados do argumento também podem ser qualificados pelo esquema.

Muitas funções nativas do PostgreSQL aceitam o OID de uma tabela, ou outro tipo de objeto de banco de dados, e por conveniência são declarados como tendo o tipo de dados regclass (ou o tipo de dados alias de OID apropriado), significando não ser necessário procurar manualmente o OID do objeto, permitindo apenas inserir o seu nome como literal cadeia de caracteres. Por exemplo, se a função nextval(regclass) recebe o OID de uma relação de sequência, então pode ser chamada assim:

nextval('foo')                 opera na sequência foo
nextval('FOO')                 idêntico ao acima
nextval('"Foo"')               opera na sequência Foo
nextval('meu_esquema.foo')     opera em meu_esquema.foo
nextval('"meu_esquema".foo')   idêntico ao acima
nextval('foo')                 pesquisa o caminho de procura por foo

Nota

Quando se escreve o argumento de tal função como literal cadeia de caracteres sem adornos, a cadeia se torna uma constante do tipo de dados regclass (ou do tipo de dados apropriado). Como esse é realmente apenas um OID, será rastreado o objeto originalmente identificado, apesar da posterior troca de nome, reatribuição de esquema etc. Esse comportamento de vinculação precoce (early binding) [58] é geralmente desejável para referências de objetos em padrões de coluna e visões. Mas às vezes pode-se desejar a vinculação tardia (late binding), onde a referência do objeto é resolvida em tempo de execução. Para obter o comportamento de vinculação tardia, deve-se forçar a constante a ser armazenada como text, em vez de regclass:

nextval('foo'::text)      foo é procurado em tempo de execução

Também podem ser usadas a função to_regclass() e suas irmãs para realizar a procura em tempo de execução. Veja a Tabela 9.76.

Outro exemplo prático de uso do tipo de dados regclass é procurar o OID de uma tabela listada nas visões do esquema de informações, que não fornecem esses OIDs diretamente. Pode-se, por exemplo, desejar chamar a função pg_relation_size(), que requer o OID da tabela. Considerando as regras acima, a maneira correta de fazer isto é:

SELECT table_schema, table_name,
       pg_relation_size((quote_ident(table_schema) || '.' ||
                         quote_ident(table_name))::regclass)
FROM information_schema.tables
WHERE ...

A função quote_ident() cuida de colocar aspas nos identificadores quando for necessário. A forma aparentemente mais fácil

SELECT pg_relation_size(table_name)
FROM information_schema.tables
WHERE ...

não é recomendada, porque vai falhar para tabelas fora de seu caminho de procura, ou que tenham nomes que exijam aspas.

Uma propriedade adicional da maioria dos tipos de dados alias de OID é a criação de dependências. Se uma constante de um desses tipos de dados aparecer em uma expressão armazenada (como expressão de padrão de uma coluna, ou visão), ela cria uma dependência no objeto referenciado. Por exemplo, se uma coluna tiver como expressão de padrão nextval('minha_seq'::regclass), o PostgreSQL entende que a expressão de padrão depende da sequência minha_seq, portanto o sistema não permite que a sequência seja excluída, sem que primeiro seja removida a expressão de padrão. A forma alternativa nextval('minha_seq'::text) não cria dependência. (regrole é uma exceção a essa propriedade. Não são permitidas constantes desse tipo de dados em expressões armazenadas.)

Outro tipo de dados identificador usado pelo sistema é o xid, ou identificador de transação (abreviado como xact). Esse é o tipo de dados das colunas do sistema xmin e xmax. Os identificadores de transação são quantidades de 32 bits. Em alguns contextos, é usada a forma alternativa de 64 bits xid8. Ao contrário dos valores xid, os valores xid8 aumentam estritamente monotonicamente, não podendo ser reutilizados durante o tempo de vida de um agrupamento (cluster) de bancos de dados. Veja a Seção 67.1 para obter mais detalhes.

Um terceiro tipo de dados de identificador usado pelo sistema é o cid, ou identificador de comando. Esse é o tipo de dados das colunas do sistema cmin e cmax. Os identificadores de comando também são quantidades de 32 bits.

O último tipo de dados de identificador usado pelo sistema é o tid, ou identificador de tupla (identificador de linha). Esse é o tipo de dados da coluna do sistema ctid. Um ID de tupla é um par (número de bloco, índice da tupla dentro do bloco) que identifica a localização física da linha na sua tabela.

(As colunas do sistema são explicadas com mais detalhes na Seção 5.6.)



[58] A vinculação refere-se ao processo de conversão de identificadores (como nomes de variáveis e de funções) em endereços. A vinculação é feita para cada variável e função. Para as funções, significa combinar a chamada com a definição correta da função pelo compilador. Ocorre em tempo de compilação ou em tempo de execução. Early Binding (polimorfismo em tempo de compilação), como o nome indica, o compilador (ou vinculador) associa diretamente um endereço à chamada da função. Early binding and Late binding in C++ (N. T.)