sql >> Base de Datos >  >> RDS >> PostgreSQL

Entendiendo la conversión de bytea a oid

El elenco no es un verdadero elenco. Es solo (ab) usar la sintaxis conveniente. Un objeto grande (LO) se crea en segundo plano, que se almacena por separado y se devuelve el OID que hace referencia a él.

Por documentación:

El OID devuelto es básicamente un FK al PK de la tabla del sistema pg_largeobject .

CREATE TABLE es completamente independiente de la función y pseudo-cast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

Es solo un caso de uso típico para el modelo de asignación creado anteriormente, que se hace evidente en la siguiente línea que olvidó citar:

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

¿Qué sucede aquí?

El tipo de datos lo es un dominio sobre el tipo base oid , creado por el módulo adicional lo (incorrectamente mencionado como "paquete lo_manage" en entidad del blog de Grace Batumbya ). Por documentación:

La función decode() devuelve bytea . El INSERT sentencia asigna el bytea valor a la columna largeObj , que desencadena una conversión de asignación a su tipo lo , y ahí es donde entra en juego el elenco anterior.

Advertencia/Corrección/Actualización

La entrada del blog está descuidada y desactualizada por ahora.

  • No se molesta en mencionar que (por documentación ):

    Efectivamente, debes ser superusuario.

  • Error tipográfico en CREATE TABLE :nombre de columna y tipo invertidos.

  • La definición de la función es detallada e ineficiente. Esto sería mejor (para Postgres 9.3 o mayor):

    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.

Hay un incorporado función para esto en Postgres 9.4 . Usa eso en su lugar:

lo_from_bytea(loid oid, string bytea)

De las notas de la versión :

Para CREATE CAST (según documentación ):

Sugiero una variante sobrecargada con solo un 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;

Dado que el pseudo-cast tiene un efecto secundario bastante grande, no estoy convencido de hacer de eso una ASSIGNMENT emitir. Probablemente comenzaría con solo explícito: