SQL para ler XML do arquivo no banco de dados PostgreSQL

12

Como escrever SQL para ler um arquivo XML em um XMLvalor do PostgreSQL ?

O PostgreSQL possui um tipo de dados XML nativo com a XMLPARSEfunção de analisar uma sequência de texto para esse tipo. Ele também tem maneiras de ler dados do sistema de arquivos; a COPYdeclaração, entre outros.

Mas não vejo uma maneira de escrever instruções SQL nativas do PostgreSQL para ler o conteúdo de uma entrada do sistema de arquivos e usá-la para preencher um XMLvalor. Como posso fazer isso?

nariz grande
fonte

Respostas:

10

Semelhante a esta resposta a uma pergunta anterior, e se você não quiser as restrições depg_read_file() (em resumo: pg_read_filenão pode ler arquivos fora do diretório do banco de dados e lê texto na codificação de caracteres da sessão atual).

Esta função funciona para qualquer caminho, mas precisa ser criada como superusuário:

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
begin
  select lo_import(p_path) into l_oid;
  select lo_get(l_oid) INTO p_result;
  perform lo_unlink(l_oid);
end;$$;

lo_get foi introduzido na 9.4, portanto, para versões mais antigas, você precisaria de:

create or replace function stack.bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
  r record;
begin
  p_result := '';
  select lo_import(p_path) into l_oid;
  for r in ( select data 
             from pg_largeobject 
             where loid = l_oid 
             order by pageno ) loop
    p_result = p_result || r.data;
  end loop;
  perform lo_unlink(l_oid);
end;$$;

então:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;
Jack diz que tenta topanswers.xyz
fonte
1
+1, obrigado por apontar que existem limites para as funções de leitura de arquivos.
precisa saber é
1
+1 truque legal para contornar pg_read_file(). O mesmo também pode ser alcançado com uma tabela temporária e COPY- preenche apenas 1 coluna de 1 linha.
precisa
4

A pg_read_binary_filefunção pode fazer isso.

Possui limitações: novo no PostgreSQL 9.1 ou superior; deve ser uma sessão pertencente ao superusuário do banco de dados; deve ler um arquivo no diretório do banco de dados ou abaixo. Esses são aceitáveis ​​no meu caso de uso.

Portanto, o seguinte funcionará para criar um XMLvalor nativo a partir de um arquivo:

-- PostgreSQL 9.1 or later.
SELECT
    XMLPARSE(DOCUMENT convert_from(
        pg_read_binary_file('foo.xml'), 'UTF8'));

No PostgreSQL 8.3 - 9.0, a pg_read_filefunção pode ser usada, com a limitação adicional de que você não pode especificar uma codificação específica do arquivo (ele lê o arquivo como texto na codificação da sessão atual).

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
nariz grande
fonte
3

Publiquei uma implementação completa do que você está solicitando em uma resposta recente ao SO .

Os principais recursos são a xpath()função, pg_read_file()manipulação de array, funções plpgsql, ..

Erwin Brandstetter
fonte
Bastante diferente (e mais pesado) do que eu preciso neste caso. Mas +1 pela boa direção, obrigado.
precisa saber é
Não é que pesos pesados, o meu exemplo é apenas muito completo, com elementos redundantes para demonstrar variantes de sintaxe.
Erwin Brandstetter