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

¿Obtener el tamaño del objeto grande en la consulta de PostgreSQL?

No es que haya usado objetos grandes, pero mirando los documentos:http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Creo que debe usar la misma técnica que requieren algunas API del sistema de archivos:busque hasta el final, luego indique la posición. PostgreSQL tiene funciones SQL que parecen envolver las funciones C internas. No pude encontrar mucha documentación, pero esto funcionó:

CREATE OR REPLACE FUNCTION get_lo_size(oid) RETURNS bigint
VOLATILE STRICT
LANGUAGE 'plpgsql'
AS $$
DECLARE
    fd integer;
    sz bigint;
BEGIN
    -- Open the LO; N.B. it needs to be in a transaction otherwise it will close immediately.
    -- Luckily a function invocation makes its own transaction if necessary.
    -- The mode x'40000'::int corresponds to the PostgreSQL LO mode INV_READ = 0x40000.
    fd := lo_open($1, x'40000'::int);
    -- Seek to the end.  2 = SEEK_END.
    PERFORM lo_lseek(fd, 0, 2);
    -- Fetch the current file position; since we're at the end, this is the size.
    sz := lo_tell(fd);
    -- Remember to close it, since the function may be called as part of a larger transaction.
    PERFORM lo_close(fd);
    -- Return the size.
    RETURN sz;
END;
$$; 

Probándolo:

-- Make a new LO, returns an OID e.g. 1234567
SELECT lo_create(0);

-- Populate it with data somehow
...

-- Get the length.
SELECT get_lo_size(1234567);

Parece que la funcionalidad LO está diseñada para usarse principalmente a través del cliente o mediante la programación del servidor de bajo nivel, pero al menos le han proporcionado algunas funciones visibles de SQL, lo que hace posible lo anterior. Hice una consulta para SELECT relname FROM pg_proc where relname LIKE 'lo%' para ponerme en marcha. Vagos recuerdos de programación en C y un poco de investigación para el modo x'40000'::int y SEEK_END = 2 se necesitaba valor para el resto!