Перейти к основному содержимому

Ограничения XML и совместимость с SQL/XML

примечание

Эта страница переведена при помощи нейросети GigaChat.

Значительные изменения в спецификациях, связанных с XML, в стандарте ISO/IEC 9075-14 (SQL/XML), были внесены в SQL: 2006. Реализация типа данных XML и связанных функций в PostgreSQL во многом следует более раннему изданию 2003 года, с некоторыми заимствованиями из последующих изданий. В частности:

  • Там, где текущий стандарт предоставляет семейство типов XML-данных для хранения «документ» или «содержание» в не типизированной или типизированной версии XML-схемы, а также тип XML(SEQUENCE), предназначенный для хранения произвольных фрагментов содержимого XML, PostgreSQL предоставляет единственный тип xml, который может хранить «документ» или «содержимое». Нет эквивалента стандартного типа «последовательность».
  • PostgreSQL предоставляет две функции, представленные в SQL:2006, но в вариантах, которые используют язык XPath 1.0 вместо XML-запроса, указанного для них в стандарте.

В этом разделе представлены некоторые различия, с которыми можно столкнуться.

Запросы ограничены XPath 1.0​

PostgreSQL-специфические функции xpath() и xpath_exists() запрашивают документы XML с использованием языка XPath. PostgreSQL также предоставляет варианты только для XPath стандартных функций XMLEXISTS и XMLTABLE, которые официально используют язык XQuery. Для всех этих функций PostgreSQL полагается на библиотеку libxml2, которая предоставляет только XPath 1.0.

Существует сильная связь между языком XQuery и версиями XPath 2.0 и более поздними: любое выражение, которое синтаксически корректно и успешно выполняется в обоих случаях, дает один и тот же результат (с незначительным исключением для выражений, содержащих числовые ссылки на символы или предопределенные ссылки на сущности, которые XQuery заменяет соответствующим символом, а XPath оставляет их без изменений). Но такой связи нет между этими языками и XPath 1.0, это был более ранний язык и отличается во многих отношениях.

Есть два типа ограничений, о которых следует помнить: ограничение от XQuery до XPath для функций, указанных в стандарте SQL, и ограничение XPath до версии 1.0 как для стандартных, так и для PostgreSQL-специфических функций.

Ограничение XQuery до XPath​

Функции XQuery, выходящие за рамки XPath, включают:

  • Выражения XQuery могут создавать и возвращать новые узлы XML, а также все возможные значения XPath. XPath может создавать и возвращать значения атомарных типов (числа, строки и т.д.), но может возвращать только узлы XML, которые уже присутствовали в документах, предоставленных в качестве входных данных для выражения.
  • В XQuery есть конструкции управления для итерации, сортировки и группировки.
  • XQuery позволяет объявлять и использовать локальные функции.

Недавние версии XPath начинают предлагать возможности, перекрывающие эти (такие как функциональный стиль for-each и sort, анонимные функции и parse-xml для создания узла из строки), но такие функции не были доступны до XPath 3.0.

Ограничение 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 действительно всегда возвращает наборы узлов для PostgreSQL с их членами в том же относительном порядке, что и во входном документе. Его документация не обязывает к такому поведению, и выражение XPath 1.0 не может контролировать его.

  • Хотя XQuery/XPath предоставляет все типы, определенные в XML-схеме, и многие операторы и функции над этими типами, 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" ложны, потому что каждый из них является числовым сравнением двух NaNs. В отличие от этого, = и != сравнивают строки как строки.

  • XPath 1.0 размывает различие между сравнениями значений и общими сравнениями, как их определяют XQuery/XPath. Как sale/@hatsize = 7, так и sale/@customer = "alice" являются сравнениями с экзистенциальной квантификацией, истинными, если существует любой sale со значением данного атрибута, но sale/@taxable = false() - это сравнение значения с эффективным логическим значением всего набора узлов. Это верно только в том случае, если ни один sale вообще не имеет атрибута taxable.

  • В модели данных XQuery/XPath узел документа может иметь либо форму документа (т.е. ровно один верхний элемент с комментариями и инструкциями обработки вне его), либо форму содержимого (с ослабленными ограничениями). Его эквивалент в XPath 1.0, корневой узел, может быть только в форме документа. Это часть причины того, что значение xml, переданное в качестве элемента контекста любой функции PostgreSQL, основанной на XPath, должно находиться в форме документа.

Различия, выделенные здесь, не все из них. В XQuery и версиях XPath 2.0 и более поздних существует режим совместимости с XPath 1.0, а списки функций библиотеки W3C изменений и языковых изменений, применяемых в этом режиме, предлагают более полный (но все еще не исчерпывающий) отчет о различиях. Режим совместимости не может сделать более поздние языки точно эквивалентными XPath 1.0.

Преобразования между типами данных SQL и XML и значениями​

В SQL:2006 и позже оба направления преобразования между стандартными типами данных SQL и типами схемы XML указаны точно. Однако правила выражены с использованием типов и семантики XQuery/XPath и не имеют прямого применения к другой модели данных XPath 1.0.

Когда PostgreSQL сопоставляет значения данных SQL с XML (как в xmlelement), или XML с SQL (как в выходных столбцах xmltable), за исключением нескольких случаев, рассматриваемых особо, PostgreSQL просто предполагает, что форма строки XPath 1.0 типа данных XML будет действительна в виде текстового ввода для типа данных SQL и наоборот. Это правило обладает простотой при создании результатов, аналогичных указанным в стандарте, для многих типов данных.

Там, где совместимость с другими системами вызывает беспокойство, для некоторых типов данных может потребоваться явное использование функций форматирования типов данных, чтобы получить стандартные сопоставления.

Непреднамеренные ограничения реализации​

Этот раздел касается ограничений, которые не присущи библиотеке libxml2, но применимы к текущей реализации в PostgreSQL.

Поддерживается только механизм передачи BY VALUE​

Стандарт SQL определяет два механизма передачи, которые применяются при передаче аргумента XML из SQL в функцию XML или получении результата: BY REF, в котором конкретное значение XML сохраняет свою узловую идентичность, и BY VALUE, в котором передается содержимое XML, но узловая идентичность не сохраняется. Механизм может быть указан перед списком параметров в качестве механизма по умолчанию для всех них или после любого параметра для замены значения по умолчанию.

Чтобы проиллюстрировать разницу, если x является значением XML, эти два запроса в среде 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);

PostgreSQL примет BY VALUE или BY REF в конструкции XMLEXISTS или XMLTABLE, но игнорирует их. Тип данных xml содержит сериализованное представление символьной строки, поэтому нет идентичности узла, которую нужно сохранить, и передача всегда эффективно BY VALUE.

Невозможно передать именованные параметры запросам​

Функции на основе XPath поддерживают передачу одного параметра для использования в качестве контекстного элемента выражения XPath, но не поддерживают передачу дополнительных значений, доступных выражению в виде именованных параметров.

Нет типа XML(SEQUENCE)​

Тип данных PostgreSQL xml может содержать значение только в форме DOCUMENT или CONTENT. Элемент контекста выражения XQuery/XPath должен быть единственным узлом XML или атомарным значением, но XPath 1.0 дополнительно ограничивает его до единственного узла XML и не имеет типа узлов, допускающего CONTENT. В итоге хорошо сформированный DOCUMENT является единственной формой значения XML, которую PostgreSQL может предоставить в качестве элемента контекста XPath.