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

Obter o tamanho do objeto grande na consulta do PostgreSQL?


Não que eu tenha usado objetos grandes, mas olhando os documentos:http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Eu acho que você tem que usar a mesma técnica que algumas APIs de sistema de arquivos exigem:busque até o final, depois diga a posição. O PostgreSQL tem funções SQL que parecem envolver as funções C internas. Não consegui encontrar muita documentação, mas isso funcionou:
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;
$$; 

Testando:
-- 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 a funcionalidade LO foi projetada para ser usada principalmente por meio do cliente ou por meio de programação de servidor de baixo nível, mas pelo menos eles forneceram algumas funções visíveis do SQL para isso, o que torna possível o acima. Eu fiz uma consulta para SELECT relname FROM pg_proc where relname LIKE 'lo%' para eu começar. Memórias vagas de programação C e um pouco de pesquisa para o modo x'40000'::int e SEEK_END = 2 valor eram necessários para o resto!