D.3. Límites de XML y conformidad con SQL/XML #

D.3.1. Las consultas están restringidas a XPath 1.0
D.3.2. Límites incidentales de la implementación

En SQL:2006 se introdujeron revisiones significativas a las especificaciones relacionadas con XML en ISO/IEC 9075-14 (SQL/XML). La implementación en PostgreSQL del tipo de datos XML y las funciones relacionadas sigue en gran medida la edición anterior de 2003, con algunos préstamos de ediciones posteriores. En particular:

Esta sección presenta algunas de las diferencias resultantes con las que te puedes encontrar.

D.3.1. Las consultas están restringidas a XPath 1.0 #

Las funciones específicas de PostgreSQL xpath() y xpath_exists() realizan consultas en documentos XML utilizando el lenguaje XPath. PostgreSQL también proporciona variantes exclusivas de XPath de las funciones del estándar XMLEXISTS y XMLTABLE, que oficialmente utilizan el lenguaje XQuery. Para todas estas funciones, PostgreSQL depende de la biblioteca libxml2, que solo proporciona XPath 1.0.

Existe una fuerte conexión entre el lenguaje XQuery y las versiones de XPath 2.0 y posteriores: cualquier expresión que sea sintácticamente válida y se ejecute con éxito en ambos produce el mismo resultado (con una pequeña excepción para las expresiones que contienen referencias a caracteres numéricos o referencias a entidades predefinidas, que XQuery reemplaza con el carácter correspondiente mientras que XPath las deja tal cual). Pero no existe tal conexión entre estos lenguajes y XPath 1.0; este era un lenguaje anterior y difiere en muchos aspectos.

Hay dos categorías de limitaciones a tener en cuenta: la restricción de XQuery a XPath para las funciones especificadas en el estándar SQL, y la restricción de XPath a la versión 1.0 tanto para las funciones del estándar como para las específicas de PostgreSQL.

D.3.1.1. Restricción de XQuery a XPath #

Las características de XQuery más allá de las de XPath incluyen:

  • Las expresiones XQuery pueden construir y devolver nuevos nodos XML, además de todos los valores posibles de XPath. XPath puede crear y devolver valores de los tipos atómicos (números, cadenas, etc.) pero solo puede devolver nodos XML que ya estaban presentes en los documentos suministrados como entrada de la expresión.

  • XQuery tiene constructores de control para iteración, ordenamiento y agrupación.

  • XQuery permite la declaración y uso de funciones locales.

Las versiones recientes de XPath comienzan a ofrecer capacidades que se superponen con estas (como for-each y sort de estilo funcional, funciones anónimas y parse-xml para crear un nodo a partir de una cadena), pero estas características no estaban disponibles antes de XPath 3.0.

D.3.1.2. Restricción de XPath a 1.0 #

Para los desarrolladores familiarizados con XQuery y XPath 2.0 o posterior, XPath 1.0 presenta una serie de diferencias con las que lidiar:

  • El tipo fundamental de una expresión XQuery/XPath, la secuencia (sequence), que puede contener nodos XML, valores atómicos o ambos, no existe en XPath 1.0. Una expresión de la versión 1.0 solo puede producir un conjunto de nodos (que contiene cero o más nodos XML) o un único valor atómico.

  • A diferencia de una secuencia de XQuery/XPath, que puede contener cualquier elemento deseado en cualquier orden deseado, un conjunto de nodos de XPath 1.0 no tiene un orden garantizado y, como cualquier conjunto, no permite múltiples apariciones del mismo elemento.

    Note

    La biblioteca libxml2 parece devolver siempre conjuntos de nodos a PostgreSQL con sus miembros en el mismo orden relativo que tenían en el documento de entrada. Su documentación no se compromete con este comportamiento, y una expresión XPath 1.0 no puede controlarlo.

  • Mientras que XQuery/XPath proporciona todos los tipos definidos en XML Schema y muchos operadores y funciones sobre esos tipos, XPath 1.0 solo tiene conjuntos de nodos y los tres tipos atómicos boolean, double y string.

  • XPath 1.0 no tiene operador condicional. Una expresión XQuery/XPath como if ( hat ) then hat/@size else "no hat" no tiene equivalente en XPath 1.0.

  • XPath 1.0 no tiene operador de comparación de orden para cadenas. Tanto "cat" < "dog" y "cat" > "dog" son falsos, porque cada uno es una comparación numérica de dos NaN. Por el contrario, = y != sí comparan las cadenas como cadenas.

  • XPath 1.0 difumina la distinción entre comparaciones de valor y comparaciones generales tal como las define XQuery/XPath. Tanto sale/@hatsize = 7 y sale/@customer = "alice" son comparaciones cuantificadas existencialmente, verdaderas si hay algún sale con el valor dado para el atributo, pero sale/@taxable = false() es una comparación de valor respecto al valor booleano efectivo de todo un conjunto de nodos. Es verdadera solo si ningún sale tiene un atributo taxable en absoluto.

  • En el modelo de datos de XQuery/XPath, un nodo de documento puede tener forma de documento (es decir, exactamente un elemento de nivel superior, con solo comentarios e instrucciones de procesamiento fuera de él) o forma de contenido (con esas restricciones relajadas). Su equivalente en XPath 1.0, el nodo raíz, solo puede estar en forma de documento. Esta es parte de la razón por la que un valor de tipo xml pasado como elemento de contexto a cualquier función basada en XPath de PostgreSQL debe estar en forma de documento.

Las diferencias señaladas aquí no son todas. En XQuery y las versiones 2.0 y posteriores de XPath, existe un modo de compatibilidad con XPath 1.0, y las listas del W3C de cambios en la biblioteca de funciones y cambios en el lenguaje aplicados en ese modo ofrecen un relato más completo (pero aún no exhaustivo) de las diferencias. El modo de compatibilidad no puede hacer que los lenguajes posteriores sean exactamente equivalentes a XPath 1.0.

D.3.1.3. Mapeos entre tipos de datos y valores SQL y XML #

En SQL:2006 y posteriores, ambas direcciones de conversión entre los tipos de datos SQL estándar y los tipos XML Schema se especifican de forma precisa. Sin embargo, las reglas se expresan utilizando los tipos y la semántica de XQuery/XPath, y no tienen aplicación directa al modelo de datos diferente de XPath 1.0.

Cuando PostgreSQL mapea valores de datos SQL a XML (como en xmlelement), o XML a SQL (como en las columnas de salida de xmltable), excepto por unos pocos casos tratados especialmente, PostgreSQL simplemente asume que la forma de cadena de texto de XPath 1.0 del tipo de datos XML será válida como la forma de entrada de texto del tipo de datos SQL, y viceversa. Esta regla tiene la virtud de la simplicidad a la vez que produce, para muchos tipos de datos, resultados similares a los mapeos especificados en el estándar.

Cuando la interoperabilidad con otros sistemas sea una preocupación, para algunos tipos de datos puede ser necesario utilizar explícitamente funciones de formato de tipo de datos (como las de Section 9.8) para producir los mapeos del estándar.

D.3.2. Límites incidentales de la implementación #

Esta sección se refiere a los límites que no son inherentes a la biblioteca libxml2, sino que se aplican a la implementación actual en PostgreSQL.

D.3.2.1. Solo se soporta el mecanismo de paso BY VALUE #

El estándar SQL define dos mecanismos de paso (passing mechanisms) que se aplican al pasar un argumento XML de SQL a una función XML o al recibir un resultado: BY REF, en el que un valor XML particular conserva su identidad de nodo, y BY VALUE, en el que se pasa el contenido del XML pero no se preserva la identidad del nodo. Se puede especificar un mecanismo antes de una lista de parámetros, como mecanismo por defecto para todos ellos, o después de cualquier parámetro, para anular el comportamiento por defecto.

Para ilustrar la diferencia, si x es un valor XML, estas dos consultas en un entorno SQL:2006 producirían verdadero (true) y falso (false), respectivamente:

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

PostgreSQL aceptará BY VALUE o BY REF en un constructor XMLEXISTS o XMLTABLE, pero los ignora. El tipo de datos xml almacena una representación serializada en cadena de caracteres, por lo que no hay identidad de nodo que preservar, y el paso siempre es efectivamente BY VALUE.

D.3.2.2. No se pueden pasar parámetros con nombre a las consultas #

Las funciones basadas en XPath admiten el paso de un parámetro para que sirva como elemento de contexto de la expresión XPath, pero no admiten el paso de valores adicionales para que estén disponibles en la expresión como parámetros con nombre.

D.3.2.3. No existe el tipo XML(SEQUENCE) #

El tipo de datos xml de PostgreSQL solo puede contener un valor en forma DOCUMENT o CONTENT. El elemento de contexto de una expresión XQuery/XPath debe ser un único nodo XML o valor atómico, pero XPath 1.0 lo restringe aún más para que sea solo un nodo XML, y no tiene ningún tipo de nodo que permita CONTENT. El resultado es que un DOCUMENT bien formado es la única forma de valor XML que PostgreSQL puede suministrar como elemento de contexto de XPath.