PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Entendendo o elenco de bytea para oid


O elenco não é um verdadeiro elenco. É apenas (ab)usando a sintaxe conveniente. Um objeto grande (LO) é criado em segundo plano que é armazenado separadamente e o OID que faz referência a ele é retornado.

Por documentação:

O OID retornado é basicamente um FK para o PK da tabela do sistema pg_largeobject .

CRIAR TABELA é completamente independente da função e pseudo-cast.
CREATE TABLE bytea_to_lo (
   largeObj lo 
);

É apenas um caso de uso típico para o elenco de atribuição criado acima, que fica aparente na seguinte linha que você esqueceu de citar:
INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex'));

O que acontece aqui?


O tipo de dados lo é um domínio sobre o tipo base oid , criado pelo módulo adicional lo (referenciado incorretamente como "pacote lo_manage" no entidade do blog de Grace Batumbya ). Por documentação:

A função decode() retorna bytea . O INSERIR declaração atribui o bytea valor para a coluna largeObj , que aciona uma conversão de atribuição para seu tipo lo , e é aí que entra o elenco acima.

Aviso/Corretivo/Atualização


A entrada do blog é desleixada e desatualizada agora.

  • Não se preocupe em mencionar isso (por documentação ):

    Efetivamente, você deve ser superusuário.

  • Erro de digitação em CREATE TABLE :nome e tipo da coluna invertidos.

  • A definição da função é detalhada e ineficiente. Isso seria melhor (para Postgres 9.3 ou mais):
    CREATE OR REPLACE FUNCTION blob_write(bytea)
      RETURNS oid AS
    $func$
    DECLARE
       loid oid := lo_create(0);
       lfd  int := lo_open(loid,131072);  -- = 2^17 = x2000
       -- symbolic constant defined in the header file libpq/libpq-fs.h
       -- #define   INV_WRITE   0x00020000
    BEGIN
       PERFORM lowrite(lfd, $1);
       PERFORM lo_close(lfd);
       RETURN loid;
    END
    $func$  LANGUAGE plpgsql VOLATILE STRICT;
    

    SQL Fiddle.

Há um integrado função para isso no Postgres 9.4 . Use isso em vez disso:
lo_from_bytea(loid oid, string bytea)

Das notas de versão :

Para CREATE CAST (por documentação ):

Sugiro uma variante sobrecarregada com apenas um bytea parâmetro:
CREATE OR REPLACE FUNCTION lo_from_bytea(bytea)
   RETURNS oid LANGUAGE sql AS
'SELECT lo_from_bytea(0, $1)';

CREATE CAST (bytea AS oid) WITH FUNCTION lo_from_bytea(bytea) AS ASSIGNMENT;

Como o pseudo-cast tem um grande efeito colateral, não estou convencido de fazer disso uma ASSIGNMENT elenco. Eu provavelmente começaria com apenas explícito: