it-swarm-eu.dev

SQL pro čtení XML ze souboru do PostgreSQL databáze

Jak mohu napsat SQL pro čtení XML souboru do PostgreSQL XML hodnoty?

PostgreSQL má nativní datový typ XML s funkcí XMLPARSE pro analýzu textového řetězce na tento typ. Má také způsoby, jak číst data ze souborového systému; mimo jiné prohlášení COPY.

Ale nevidím způsob, jak psát nativní příkazy SQL PostgreSQL pro čtení obsahu ze záznamu souborového systému a použít jej k naplnění hodnoty XML. Jak to mohu udělat?

12
bignose

Funkce pg_read_binary_file to dokáže.

Má omezení: nové v PostgreSQL 9.1 nebo vyšší; musí to být relace vlastněná superuživatelem databáze; musí číst soubor v adresáři databáze nebo níže. Ty jsou v mém případě použití přijatelné.

Při vytváření nativní hodnoty XML ze souboru tedy bude fungovat následující:

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

V PostgreSQL 8.3 - 9.0 lze použít funkci pg_read_file , s dalším omezením, že nemůžete specifikovat kódování specifické pro soubor (v aktuálním souboru jej přečte jako text kódování relace).

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

Podobně jako this odpověď na předchozí otázku, a pokud nechcete omezení pg_read_file() (zkrátka: pg_read_file neumí číst soubory mimo adresář databáze a čte text v kódování znaků aktuální relace).

Tato funkce funguje pro jakoukoli cestu, ale musí být vytvořena jako superuživatel:

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 byl představen v 9.4, takže pro starší verze byste potřebovali:

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

pak:

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

Zveřejnil jsem kompletní implementaci toho, co požadujete v nedávná odpověď na SO .

Klíčovými funkcemi jsou funkce xpath(), pg_read_file(), ovládání pole, funkce plpgsql, ..

3
Erwin Brandstetter