PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 10.23 » Annexes » Conformité SQL » Limites XML et conformité au SQL/XML

D.3. Limites XML et conformité au SQL/XML

Des révisions significatives des spécifications relatives au XML dans ISO/IEC 9075-14 (SQL/XML) ont été introduites avec SQL:2006. L'implémentation de PostgreSQL du type de données XML et des fonctions relatives suit largement l'édition 2003, avec quelques emprunts aux éditions ultérieures. En particulier :

  • Quand le standard actuel fournit une famille de types de données XML pour contenir un « document » ou un « content » dans des variants non typés ou typés XML Schema, et un type XML(SEQUENCE) pour contenir des parties arbitraires d'un contenu XML, PostgreSQL fournit le seul type xml, qui peut contenir « document » ou « content ». Il n'y a pas d'équivalent au type « sequence » du standard.

  • PostgreSQL fournit deux fonctions introduites avec SQL:2006, mais des variantes qui utilisent le langage XPath 1.0, plutôt que XML Query comme indiqué dans le standard.

Cette section présente certaines des différences résultantes que vous pourriez rencontrer.

D.3.1. Les requêtes sont restreintes à XPath 1.0

Les fonctions PostgreSQL xpath() et xpath_exists() requêtent des documents XML en utilisant le langage XPath. PostgreSQL fournit aussi les variantes XPath des fonctions standards XMLEXISTS et XMLTABLE, qui utilisent officiellement le langage XQuery. Pour toutes ces fonctions, PostgreSQL se base sur la bibliothèque libxml2, qui fournit seulement XPath 1.0.

Il existe un lien fort entre le langage XQuery et XPath version 2.0 et ultérieures : toute expression qui est syntaxiquement valide et qui exécute avec succès dans les deux langages produit le même résultat (avec une exception mineure pour les expressions contenant des références numériques de caractères ou des références d'entités prédéfinies, que XQuery remplace avec le caractère correspondant alors que XPath les ignore). Mais il n'y a pas un tel lien entre ces langages et XPath 1.0 ; il s'agissait d'un langage précédent et il diffère en de nombreux aspects.

Il existe deux catégories de limitation à garder à l'esprit : la restriction de XQuery à XPath pour les fonctions spécifiées dans le standard SQL standard, et la restriction de XPath à version 1.0 pour les fonctions standards et spécifiques à PostgreSQL.

D.3.1.1. Restriction de XQuery à XPath

Les fonctionnalités de XQuery en dehors de celles d'XPath incluent :

  • Les expressions XQuery peuvent construire et rnevoyer de nouveaux nœuds XML, en plus de toutes les valeurs XPath possibles. XPath peut créer et renvoyer des valeurs des types atomiques (nombres, chaînes, et ainsi de suite) mais peut seulement renvoyer des nœuds XML qui étaient déjà présents dans les documents fournis en entrée de l'expression.

  • XQuery a des constructions de contrôle pour l'itération, le tri et le regroupement.

  • XQuery permet la déclaration et l'utilisation de fonctions locales.

Les versions XPath récentes commencent à offrir des possibilités surchargeant celles-ci (comme for-each et sort, les fonctions anonymes, et parse-xml pour créer un nœud à partir d'une chaîne), mais ces fonctionnalités n'étaient pas disponibles avant XPath 3.0.

D.3.1.2. Restriction de XPath à 1.0

Pour les développeurs familiers avec XQuery et XPath 2.0 ou ultérieur, XPath 1.0 présente un certain nombre de différences :

  • Le type fondamental d'une XQuery/XPath, la sequence, qui peut contenir des nœuds XML, des valeurs atomiques, ou les deux, n'existe pas dans XPath 1.0. Une expression 1.0 peut seulement produire un ensemble de nœuds (contenant zéro ou plus de nœuds XML), ou une simple valeur atomique.

  • Contrairement à une séquence XQuery/XPath, qui peut contenir tout élément désiré dans un ordre désiré, un ensemble de nœuds XPath 1.0 n'offre pas de garantie d'ordre et, comme tout ensemble, n'autorise pas plusieurs apparences du même élément.

    Note

    La bibliothèque libxml2 ne semble pas toujours renvoyer des ensembles de nœuds à PostgreSQL avec tous leurs membres dans le même ordre relatif au document en entrée. Sa documentation ne garantie pas ce comportement, et une expression XPath 1.0 ne permet pas de la contrôler.

  • Alors que XQuery/XPath fournit tous les types définis dans un XML Schema et de nombreux opérateurs et fonctions sur ces types, XPath 1.0 a seulement les ensembles de nœuds et les trois types atomiques boolean, double et string.

  • XPath 1.0 n'a pas d'opérateur conditionnel. Toute expression XQuery/XPath telle que if ( hat ) then hat/@size else "no hat" n'a pas d'équivalent XPath 1.0.

  • XPath 1.0 n'a pas d'opération de comparaison de tri pour les chaînes. "cat" < "dog" et "cat" > "dog" sont faux parce que ce sont des comparaisons numériques de deux valeurs NaN. Par contre, = and != comparent les chaînes en tant que chaînes.

  • XPath 1.0 brouille la distinction entre comparaisons de valeurs et comparaisons générales telles que XQuery/XPath les définit.sale/@hatsize = 7 et sale/@customer = "alice" sont des comparaisons quantifiées, vrai s'il existe au moins un sale avec la valeur donnée pour l'attribut, mais sale/@taxable = false() est une comparaison de valeur pour la valeur booléenne réelle de l'ensemble complet de nœuds. C'est vrai uniquement si aucun sale n'a d'attribut taxable.

  • Dans le modèle de données XQuery/XPath, un nœud document peut avoir soit une forme document (exactement un élément de haut niveau, avec seulement des commentaires et des instructions de traitement en dehors) ou une forme contenu (avec ces contraintes diminuées). Son équivalent avec XPath 1.0, le nœud racine, peut seulement être en forme document. C'est une des raisons pour lesquelles une valeur xml passée à l'élément de contexte pour toute fonction PostgreSQL basée sur XPath doit être dans une forme document.

Les différences soulignées ici ne sont pas complètes. Dans XQuery et les versions 2.0 et ultérieures de XPath, il existe un mode de compatibilité XPath 1.0, et les listes W3C des modifications de fonctions et des modifications de langage appliqués dans ce mode offre une liste plus complète (bien que non exhaustive) des différences. Le mode de compatibilité ne peut pas rendre les nouveaux langages exactement équivalent à XPath 1.0.

D.3.1.3. Correspondances entre les types de données SQL et XML et les valeurs

Dans SQL:2006 et ultérieurs, les deux directions de conversion entre les types de données du standard SQL et les types XML Schema sont spécifiées précisément. Néanmoins, les règles sont exprimées en utilisant les types et sémantiques de XQuery/XPath, et n'ont pas d'application directe vers le modèle de données de XPath 1.0.

Quand PostgreSQL fait une correspondance des valeurs de données SQL en XML (comme dans xmlelement), ou de XML vers SQL (comme dans les colonnes en sortie de xmltable), sauf pour quelques cas traités spécifiquement, PostgreSQL suppose simplement que la chaîne XPath 1.0 du type de données XML sera valide sous la forme textuelle du type de données SQL, et inversement. Cette règle a l'avantage de la simplicité tout en produisant pour de nombreux types de données des résultats similaires aux correspondances indiquées dans le standard. Dans cette version, une conversion explicite est nécessaire si une expression de colonne xmltable produit une valeur booléenne ou double ; voir Section D.3.2.

Quand l'interopérabilité avc d'autres systèmes est importante, pour certains types de données, il pourrait être nécessaire d'utiliser explicitement les fonctions de formatage des types de données (telles que celles disponibles dans Section 9.8) pour produire les correspondances standards.

D.3.2.  Limites accidentelles de la mise en œuvre

Cette section concerne les limites qui ne sont pas inhérentes à la bibliothèque libxml2 mais s'appliquent à l'implémentation dans PostgreSQL.

D.3.2.1.  Conversion nécessaire pour la colonne de type boolean ou double avec xmltable

Une expression de colonne xmltable évaluée en un booléen ou nombre résultat XPath produira une erreur « unexpected XPath object type ». Le contournement reviendra à réécrire l'expression de colonne dans la fonction string XPath ; PostgreSQL affectera alors la valeur chaîne à une colonne SQL en sortie, de type boolean ou double.

D.3.2.2.  Résultat du chemin de colonne ou colonne de résultat SQL d'un type XML

Dans cette version, une expression de colonne xmltable qui évalue en un ensemble de nœuds XML peut être assignée à une colonne résultat SQL d'un type XML, produisant une concaténation de : pour la plupart des types de nœud dans l'ensembl de nœuds, un nœud texte contenant la valeur chaîne XPath 1.0 du nœud, mais pour un nœud élément, une copie du nœud lui-même. Un tel ensemble de nœuds pourrait être affecté à une colonne SQL d'un type non XML seulement si l'ensmble de nœuds a un seul nœud, avec la valeur textuelle de la plupart des nœuds types remplacée par une chaîne vide, la valeur textuelle d'un nœud élément remplacée avec une concaténation de seulement ses nœuds enfants directs (excluant les descendants), et la valeur textuelle d'un nœud texte ou attribut défini dans XPath 1.0. Une valeur textuelle XPath affectée à une colonne résultat d'un type XML doit être analysable comme du XML.

Il est préférable de ne pas développer du code qui se base sur ces comportements, qui ont peu de ressemblances avec les spécifications, et sont changés dans PostgreSQL 12.

D.3.2.3. Seul le mécanisme BY VALUE est supporté

Le standard SQL définit deux mécanismes de passage qui s'appliquent lors du passage d'un argument XML du SQL vers une fonction XML ou recevant un résultat : BY REF, pour lequel une valeur XML particulière conserve son identité de nœud, et BY VALUE, pour lequel le contenu du XML est passé mais l'identité du nœud n'est pas préservée. Un mécanisme peut être indiqué avant une liste de paramètres, comme mécanisme par défaut pour tous, et après un paramètre pour surcharger le mécanisme par défaut.

Pour illustrer la différence, si x est une valeur XML, ces deux requêtes produiront, respectivement, true et false dans un environnement SQL:2006 :

SELECT XMLQUERY('$a is $b' PASSING BY REF x AS a, x AS b NULL ON EMPTY);
SELECT XMLQUERY('$a is $b' PASSING BY VALUE x AS a, x AS b NULL ON EMPTY);
     

Dans cette version, PostgreSQL acceptera BY REF dans une construction XMLEXISTS ou XMLTABLE, mais l'ignorera. Le type de données xml détient une représentation textuelle sérialisée, donc il n'existe pas d'identité de nœud à préserver. Le passage est donc forcément BY VALUE.

D.3.2.4. Ne peut pas passer des paramètres nommés aux requêtes

Les fonctions basées sur XPath supportent de passer un paramètre pour servir en tant que l'élément de contexte de l'expression XPath, mais ne supportent pas de valeurs supplémentaires dans l'expression, disponibles en tant que paramètres nommés.

D.3.2.5. Aucun type XML(SEQUENCE)

Le type de données xml de PostgreSQL peut seulement détenir une valeur dans la forme DOCUMENT ou CONTENT. Un élément de contexte dans une expressions XQuery/XPath doit être un seul nœud XML ou une valeur atomique, mais XPath 1.0 restreint cela encore plus au point que ce soit seulement un nœud XML et qui n'a pas de type de nœud permettant CONTENT. La conséquence est qu'un DOCUMENT bien formé est la seule forme de valeur XML que PostgreSQL peut fournir en tant qu'élément de contexte XPath.