D.3. Ограничения XML и совместимость с SQL/XML #
В SQL:2006 были внесены значительные изменения в посвящённой XML части ISO/IEC 9075-14 (SQL/XML). Реализация типа данных XML и связанных функций в Postgres Pro в большей степени соответствует более ранней редакции, SQL:2003, с некоторыми заимствованиями из последующих редакций. В частности:
Тогда как в текущем стандарте существует семейство типов данных XML, содержащих «документы» или «содержимое» в нетипизированном виде или с типами XML Schema, а также тип
XML(SEQUENCE), содержащий произвольные части XML-документа, в Postgres Pro есть только один типxml, который может содержать «документ» или «содержимое». Определённый в стандарте тип «последовательность» в Postgres Pro отсутствует.Postgres Pro предоставляет две функции, появившиеся в SQL:2006, но вместо языка XML Query, как должно быть согласно стандарту, в них используется язык XPath 1.0.
Postgres Pro не поддерживает предложения
RETURNING CONTENTиRETURNING SEQUENCE: реализация функций, определяемых с этими предложениями в спецификации, подразумевает возврат содержимого.
В этом разделе описаны некоторые из образовавшихся в итоге различий, с которыми вы можете столкнуться.
D.3.1. Запросы ограничиваются XPath версии 1.0 #
Специфичные для Postgres Pro функции xpath() и xpath_exists() выполняют запросы к XML-документам на языке XPath. В Postgres Pro также имеются поддерживающие только XPath стандартные функции XMLEXISTS и XMLTABLE, хотя согласно стандарту они должны поддерживать XQuery. Все эти функции в Postgres Pro реализованы с использованием библиотеки libxml2, которая поддерживает только XPath 1.0.
Существует тесная связь между языком XQuery и XPath версии 2.0 и новее: любое выражение, синтаксически правильное и выполняющееся успешно, выдаёт в обоих языках одинаковые результаты (за незначительным исключением, связанным с числовым обозначением символов или использованием предопределённых сущностей — XQuery заменяет их соответствующими символами, а XPath оставляет в исходном виде). Но между XPath 1.0 и этими языками подобная связь отсутствует: он появился гораздо раньше и во многом отличается от них.
Заслуживают отдельного рассмотрения две категории ограничений: ограничение языка XQuery до XPath для функций, описанных в стандарте SQL, и ограничение XPath до версии 1.0 как для стандартизированных функций, так и для специфичных функций Postgres Pro.
D.3.1.1. Ограничение языка XQuery до XPath #
В число отличий XQuery от XPath входят:
Выражения XQuery могут выдавать не только всевозможные значения XPath, но и конструировать новые XML-узлы. XPath может создавать и возвращать значения атомарных типов (числа, строки и так далее), но выдаваемые им XML-узлы должны уже присутствовать в документе, поступившем на вход выражения.
В XQuery есть управляющие конструкции для организации циклов, сортировки и группировки.
В XQuery поддерживается объявление и использование локальных функций.
В последних версиях XPath начинают появляться возможности, пересекающиеся с имеющимися в XQuery (например, конструкции for-each, sort, анонимные функции и функция parse-xml, создающая узел из строки), но до XPath 3.0 их не было.
D.3.1.2. Ограничения XPath до версии 1.0 #
Разработчикам, знакомым с XQuery и XPath 2.0 или новее, приходится иметь дело с рядом недостатков XPath версии 1.0:
Фундаментальный тип результатов XQuery/XPath, тип
sequence, который может содержать XML-узлы, атомарные значения, и всё это вместе, в XPath 1.0 отсутствует. В 1.0 выражения могут выдавать только набор узлов (состоящих из нуля или нескольких узлов XML) или единственное атомарное значение.В отличие от последовательностей XQuery/XPath, которые могут содержать произвольные элементы в любом требующемся порядке, во множестве узлов XPath 1.0 нет гарантированного порядка, и оно, как и любое другое множество, не может содержать несколько вхождений одного элемента.
Примечание
Библиотека libxml2 не всегда возвращает в Postgres Pro наборы узлов с внутренними членами в том порядке, в котором они идут во входном документе. В её документации не гарантируется корректное поведение, а выражение XPath 1.0 не может на это воздействовать.
Тогда как XQuery/XPath поддерживают все типы, определённые в стандарте XML Schema, а также множество операторов и функций, работающих с этими типами, XPath 1.0 поддерживает только множества узлов и три атомарных типа:
boolean,doubleиstring.В XPath 1.0 отсутствует условный оператор. Выражение XQuery/XPath вида
if ( hat ) then hat/@size else "no hat"не имеет эквивалента в XPath 1.0.В XPath 1.0 нет оператора сравнения строк с упорядочиванием. Условия
"cat" < "dog"и"cat" > "dog"оба являются ложными, так как они выполняются как числовые сравнения двух значенийNaN. Условия же=и!=, напротив, сравнивают строки в виде строк.XPath 1.0 размывает разницу между сравнением значений и общими сравнениями, которая имеется в XQuery/XPath. Сравнения
sale/@hatsize = 7иsale/@customer = "alice"по сути являются количественными сравнениями, и результатом их будет истина, если существует элементsaleс заданным значением атрибута, тогда какsale/@taxable = false()— сравнение всего набора узлов с фактическим логическим значением. Его результат будет истиной, только если у элементаsaleвовсе не будет атрибутаtaxable.В модели данных XQuery/XPath узел документа может иметь либо форму документа (то есть содержать в точности один элемент верхнего уровня, снаружи которого допускаются только комментарии и инструкции обработки), либо форму содержимого (с ослабленными ограничениями). В XPath 1.0 ему соответствует корневой узел, который может иметь только форму документа. Этим отчасти объясняется то, что значение типа
xml, передаваемое в качестве элемента контекста любым функциям Postgres Pro на базе XPath, должно быть в форме документа.
Кроме отмеченных выше имеются и другие различия. В языках XQuery и XPath версии 2.0 и новее существует режим совместимости с XPath 1.0, а в документации W3C имеется перечень изменений функций и изменений в языке применительно к этому режиму. Этот перечень гораздо более полный, но тоже не исчерпывающий. Даже режим совместимости этих языков не обеспечивает их полную идентичность XPath 1.0.
D.3.1.3. Преобразование значений/типов данных между SQL и XML #
В SQL:2006 и более поздних ревизиях чётко определены преобразования между стандартными типами SQL и типами стандарта XML Schema в обе стороны. Однако эти правила выражаются в типах и понятиях, определённых в XQuery/XPath, и не могут быть непосредственно применены к другой модели данных, присущей XPath 1.0.
Когда Postgres Pro сопоставляет значения данных SQL с XML (как в функции xmlelement), или XML с SQL (как в выходных столбцах xmltable), за исключением нескольких отдельно обрабатываемых случаев, Postgres Pro просто полагает, что строка XPath 1.0, содержащая данные типа XML, будет допустимой для ввода в текстовом виде в тип данных SQL, и наоборот. Это правило добродетельно своей простотой, и при этом преобразования для многих типов данных в итоге оказываются такими, какими и должны быть согласно стандарту.
Там же, где это нужно для взаимодействия с другими системами, для некоторых типов данных можно явно использовать функции форматирования типов данных (например, описанные в Разделе 9.8) для получения преобразований, в точности соответствующих стандарту.
D.3.2. Непреднамеренные ограничения реализации #
В этом разделе описываются дополнительные ограничения, присущие текущей реализации в Postgres Pro, но не самой библиотеке libxml2.
D.3.2.1. Передача параметров только по значению (BY VALUE) #
В стандарте SQL определены два механизма передачи параметров, осуществляющих передачу XML-аргумента из SQL в XML-функцию или получение результата: BY REF, в котором конкретное значение в XML остаётся привязанным к своему узлу, и BY VALUE, в котором передаётся содержимое XML, но связь с узлом теряется. Выбрать механизм можно перед списком параметров, в качестве механизма по умолчанию для всех параметров, или после каждого отдельного параметра, переопределив тем самым выбор по умолчанию.
В качестве иллюстрации различия взгляните на следующие два запроса, которые в окружении SQL:2006 выдают true и false, если x является XML-значением:
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);Postgres Pro принимает указания BY VALUE и BY REF в конструкции XMLEXISTS или XMLTABLE, но игнорирует их. Тип xml содержит сериализованное представление данных в текстовом виде, поэтому сущность узла, которую нужно сохранять, отсутствует, и передача фактически производится по значению (BY VALUE).
D.3.2.2. Отсутствие именованных параметров запросов #
Функции на базе XPath могут принимать один параметр, служащий контекстным элементом для выражения XPath, но не поддерживают передачу дополнительных значений, которые могли бы использоваться в выражении как именованные параметры.
D.3.2.3. Отсутствие типа XML(SEQUENCE) #
Тип данных xml в Postgres Pro может содержать значение только в форме документа (DOCUMENT) или содержимого (CONTENT). Контекстный элемент выражения XQuery/XPath должен быть одиночным XML-узлом или атомарным значением, но в XPath 1.0 это может быть только XML-узел, и при этом нет типа узла, содержащего CONTENT. Как следствие, в Postgres Pro в качестве контекстного элемента XPath можно передать данные XML в единственном виде — в виде правильно оформленного документа (DOCUMENT).