SQL para leer XML del archivo en la base de datos PostgreSQL


12

¿Cómo puedo escribir SQL para leer un archivo XML en un XMLvalor PostgreSQL ?

PostgreSQL tiene un tipo de datos XML nativo con la XMLPARSEfunción de analizar una cadena de texto a ese tipo. También tiene formas de leer datos del sistema de archivos; el COPYcomunicado, entre otros.

Pero no veo una manera de escribir declaraciones SQL PostgreSQL nativas para leer el contenido de una entrada del sistema de archivos y usarlo para completar un XMLvalor. ¿Cómo puedo hacer esto?

Respuestas:


10

Similar a esta respuesta a una pregunta anterior, y si no desea las restricciones depg_read_file() (en resumen: pg_read_fileno puede leer archivos fuera del directorio de la base de datos y lee el texto en la codificación de caracteres de la sesión actual).

Esta función funciona para cualquier ruta, pero debe crearse como superusuario:

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 se introdujo en 9.4, por lo que para versiones anteriores necesitaría:

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;$$;

luego:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;

1
+1, gracias por señalar que hay límites para las funciones de lectura de archivos.
bignose

1
+1 buen truco para eludir pg_read_file(). Lo mismo también se puede lograr con una tabla temporal y COPY- complete solo 1 columna de 1 fila.
Erwin Brandstetter

4

La pg_read_binary_filefunción puede hacer esto.

Tiene limitaciones: nuevo en PostgreSQL 9.1 o superior; debe ser una sesión propiedad del superusuario de la base de datos; debe leer un archivo dentro del directorio de la base de datos o debajo. Esos son aceptables en mi caso de uso.

Entonces, lo siguiente funcionará para crear un XMLvalor nativo de un archivo:

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

En PostgreSQL 8.3 - 9.0, la pg_read_filefunción se puede utilizar, con la limitación adicional de que no puede especificar una codificación específica de archivo (lee el archivo como texto en la codificación de la sesión actual).

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

3

He publicado una implementación completa de lo que está pidiendo en una respuesta reciente sobre SO .

Las características clave son la xpath()función, pg_read_file()manejo de matriz, funciones plpgsql, ..


Bastante diferente (y más pesado) de lo que necesito en este caso. Pero +1 por la buena dirección, gracias.
bignose

No es que el peso pesado, mi ejemplo es muy completo con elementos redundantes para demostrar variantes de sintaxis.
Erwin Brandstetter
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.