PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Comprensione del cast da bytea a oid

Il cast non è un vero cast. Sta solo (ab)usando la comoda sintassi. Un oggetto grande (LO) viene creato in background che viene memorizzato separatamente e viene restituito l'OID di riferimento.

Per documentazione:

L'OID restituito è fondamentalmente un FK per il PK della tabella di sistema pg_largeobject .

CREATE TABLE è completamente indipendente dalla funzione e pseudocast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

È solo un tipico caso d'uso per il cast di assegnazione creato sopra, che diventa evidente dalla seguente riga che hai dimenticato di citare:

INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex'));

Cosa succede qui?

Il tipo di dati lo è un dominio sul tipo di base oid , creato dal modulo aggiuntivo lo (indicato erroneamente come "pacchetto lo_manage" in blog entità di Grace Batumbya ). Per documentazione:

La funzione decode() restituisce bytea . Il INSERT assegna il bytea valore alla colonna largeObj , che attiva un cast di assegnazione al suo tipo lo , ed è qui che entra in gioco il cast di cui sopra.

Avviso/Correzione/Aggiornamento

Il post del blog è sciatto e ormai obsoleto.

  • Non si preoccupa di menzionarlo (per documentazione ):

    In effetti, devi essere superutente.

  • Errore di battitura in CREATE TABLE :nome e tipo della colonna invertiti.

  • La definizione della funzione è dettagliata e inefficiente. Sarebbe meglio (per Postgres 9.3 o più vecchi):

    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.

Esiste un integrato funzione per questo in Postgres 9.4 . Usa quello invece:

lo_from_bytea(loid oid, string bytea)

Dalle note sulla versione :

Per CREATE CAST (per documentazione ):

Suggerisco una variante sovraccarica con solo un bytea parametro:

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;

Dal momento che lo pseudo-cast ha un effetto collaterale piuttosto grande, non sono convinto di renderlo un ASSIGNMENT lancio. Probabilmente inizierei con solo esplicito: