SQL pour lire XML du fichier dans la base de données PostgreSQL

12

Comment puis-je écrire du SQL pour lire un fichier XML dans une XMLvaleur PostgreSQL ?

PostgreSQL a un type de données XML natif avec la XMLPARSEfonction pour analyser une chaîne de texte vers ce type. Il a également des moyens de lire les données du système de fichiers; la COPYdéclaration, entre autres.

Mais je ne vois aucun moyen d'écrire des instructions SQL PostgreSQL natives pour lire le contenu d'une entrée de système de fichiers et l'utiliser pour remplir une XMLvaleur. Comment puis-je faire ceci?

gros nez
la source

Réponses:

10

Similaire à cette réponse à une question précédente, et si vous ne voulez pas les restrictions depg_read_file() (en bref: pg_read_filene peut pas lire les fichiers en dehors du répertoire de la base de données et lit le texte dans l'encodage des caractères de la session en cours).

Cette fonction fonctionne pour n'importe quel chemin, mais doit être créée en tant que superutilisateur:

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 a été introduit en 9.4, donc pour les anciennes versions, vous auriez besoin 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;$$;

ensuite:

select convert_from(stack.bytea_import('/tmp/test.xml'), 'utf8')::xml;
Jack dit d'essayer topanswers.xyz
la source
1
+1, merci d'avoir souligné qu'il y a des limites aux fonctions de lecture de fichiers.
bignose
1
+1 astuce à contourner pg_read_file(). La même chose peut également être obtenue avec une table temporaire et COPY- remplir seulement 1 colonne de 1 ligne.
Erwin Brandstetter
4

La pg_read_binary_filefonction peut le faire.

Il a des limites: nouveau dans PostgreSQL 9.1 ou supérieur; doit être une session appartenant au superutilisateur de la base de données; doit lire un fichier dans le répertoire de la base de données ou en dessous. Celles-ci sont acceptables dans mon cas d'utilisation.

Ainsi, les éléments suivants fonctionneront pour créer une XMLvaleur native à partir d'un fichier:

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

Dans PostgreSQL 8.3 - 9.0, la pg_read_filefonction peut être utilisée, avec la limitation supplémentaire que vous ne pouvez pas spécifier un codage spécifique au fichier (il lit le fichier sous forme de texte dans le codage de la session en cours).

-- PostgreSQL earlier than 9.1.
SELECT
    XMLPARSE(DOCUMENT pg_read_file('foo.xml'));
gros nez
la source
3

J'ai posté une implémentation complète de ce que vous demandez dans une réponse récente sur SO .

Les principales fonctionnalités sont la xpath()fonction, la pg_read_file()gestion des tableaux, les fonctions plpgsql, ..

Erwin Brandstetter
la source
Plutôt différent (et plus lourd) que ce dont j'ai besoin dans ce cas. Mais +1 pour la bonne direction, merci.
bignose
Ce n'est pas si lourd, mon exemple est juste très complet avec des éléments redondants pour démontrer les variantes de syntaxe.
Erwin Brandstetter