★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

D.3. XMLの制限とSQL/XMLへの適合 #

SQL:2006でISO/IEC 9075-14 (SQL/XML)のXML関連の仕様についての重要な改定が導入されました。 PostgreSQLのXMLデータ型と関連する関数の実装は、いくつか新しい版から取り入れつつ、主として2003以前の版に従っていました。 特に:

本章では遭遇するであろういくつかの結果の違いを示します。

D.3.1. 問い合わせはXPath 1.0に限定される #

PostgreSQL固有の関数xpath()xpath_exists()はXPath言語を使ってXML文書に問い合わせます。 PostgreSQLは、公式にはXQuery言語を使う標準関数のXMLEXISTSXMLTABLEについても、XPathのみという変形を提供しています。 これら全ての関数についてPostgreSQLは、XPath 1.0のみを提供する、libxml2ライブラリに依存しています。

XQuery言語とXPathバージョン2.0以降との間には強い関連があり、両方で構文として有効で正常に実行できる全ての式は同じ結果を生成します(数字を含む式の参照や事前定義された要素の参照について細かな例外があり、それらをXQueryは対応する文字で置換しますが、XPathはそのままにします)。 しかし、これら言語とXPath 1.0との間には、このような関連はありません。XPath 1.0はより古い言語であって多くの点で異なります。

認識すべき二つの種類の制限事項があります。 SQL標準で指定される関数に対してXQueryでなくXPathであるという制限と、標準関数でもPostgreSQL固有関数でもXPathがバージョン1.0であるという制限です。

D.3.1.1. XQueryがXPathである制限 #

XPathに含まれないXQueryの機能:

  • XQueryの式は、全てのXPathでできる値に加えて、新たなXMLノードを生成して返すことができます。 XPathは原子型(数値、文字列など)の値を作成して返すことができますが、XMLノードは入力として式に与えられる文書にあらかじめ存在するものしか返せません。

  • XQueryは構造に対する反復、並べ替え、グループ化の制御ができます。

  • XQueryでは局所関数を宣言して使用することができます。

最近のXPathバージョンはこれらをカバーする機能(関数形式のfor-eachsort、無名関数、文字列からノードを作るparse-xmlなど)を提供し始めていますが、これら機能はXPath 3.0より前では提供されません。

D.3.1.2. XPathが1.0であることによる制限 #

XQueryとXPath 2.0以降に慣れた開発者にとって、XPath 1.0には以下の対処すべき違いがあります。

  • XQuery/XPath式の基本的な型で、XMLノードや原子値、それらの両方を複数含むことができるsequenceがXPath 1.0には存在しません。 1.0の式はノードセット(0個以上のXMLノードを含む)か単独の原子値のみ生成できます。

  • 任意の要素群を任意の順序で含めることができるXQuery/XPathのシーケンスと違い、XPath 1.0のノードセットは順序保証がなく、集合のように、同じ要素が複数出現することを許しません。

    注記

    libxml2ライブラリは常に入力文書での順序に連動した同じ順序でPostgreSQLにノードセット返すように見えます。 ライブラリのドキュメントはこの振る舞いを保証していませんし、XPath 1.0式はこれを制御できません。

  • XQuery/XPathがXML Schemaで定義されたすべての型と、これらの型に対する多数の演算子や関数を提供する一方、XPath 1.0ではノードセットと3つの原子型booleandoublestringのみが使えます。

  • XPath 1.0には条件演算子がありません。 if ( hat ) then hat/@size else "no hat"といったXQuery/XPathの式は、XPath 1.0では実現できません。

  • XPath 1.0には文字列の順序比較演算子がありません。 "cat" < "dog""cat" > "dog"も、どちらも2つのNaNの数値比較であるため、偽になります。 対照的に=!=は文字列を文字列として比較します。

  • XPath 1.0では、XQuery/XPathで定義されているところの値比較一般比較の区別が曖昧です。 sale/@hatsize = 7sale/@customer = "alice"は、共に実体のある定量的な比較であり、与えられた属性に対する値を伴うsaleがあるなら真ですが、sale/@taxable = false()はノードセット全体の有効なブール値との値比較です。 taxable属性を持つsaleが全く無い場合のみ真になります。

  • XQuery/XPathデータモデルでは、ドキュメントノードはドキュメント形式(すなわちコメントと外側の処理指示だけを伴う厳密に一つだけのトップレベル要素)かコンテキスト形式(これらの制約が緩められたもの)のいずれかを持つことができます。 これに対してXPath 1.0ではルートノードはドキュメント形式のみです。 このことは、PostgreSQLのXPathに基づくどの関数に対してもコンテキスト要素として渡されるxml値がドキュメント形式でなければならない理由の一つです。

ここに挙げたものは違いの全てではありません。 XQueryと2.0以降のXPathには、XPath 1.0互換モードがあり、このモードで摘要されるW3Cの関数ライブラリの変更点言語の変更点のリストは、より完成された(しかし未だ完全ではない)違いの説明を提供します。 この互換モードは新しい言語を正確にXPath 1.0と等しくできるわけではありません。

D.3.1.3. SQLとXMLのデータ型および値のマッピング #

SQL:2006以降では、標準SQLデータ型とXMLスキーマ型の間の両方向の変換が正確に明記されています。 しかしながら、その規則はXQuery/XPathの型と意味を用いて説明されていて、XPath1.0の異なるデータモデルへの直接の適用は含まれません。

PostgreSQLがSQLデータの値からXML(xmlelementで)、あるいは、XMLからSQL(xmltableの出力列で)に変換するとき、特別扱いされる一部の場合を除いて、PostgreSQLは単純にXMLデータ型のXPath 1.0文字列形式がSQLデータ型のテキスト入力形式として有効であると想定し、逆向きの変換でも同様です。 この規則は多くのデータ型に対して実装が単純という長所を持ち、標準で明記された変換と似た結果になります。

他システムとの相互運用性が重要なところでは、一部のデータ型に対して標準の変換を実現するために明示的に(9.8にあるような)データ型整形関数を使うことがおそらく必要です。

D.3.2. その他の実装の制限 #

本節はlibxml2ライブラリ固有の制限ではないけれども、PostgreSQLの現在の実装で適用される制限について述べます。

D.3.2.1. 引き渡し機構はBY VALUEのみ対応 #

SQL標準は、SQLからXML関数にXML引数を渡す、あるいは結果を受け取るときに適用される2つの引き渡し方式を定義しています。 BY REFでは特定のXML値がそのノードIDを保持し、BY VALUEではXML内容が渡されてノードIDは保持されません。 方式は、パラメータリストの手前にそれらすべてのデフォルトとして、あるいは、各パラメータの後ろにデフォルトを上書きするものとして、指定することができます。

違いを例を挙げて示します。もしxがXML値であるなら、SQL:2006環境でのこれら2つの問合わせは、それぞれtrueとfalseを返すでしょう。

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は、XMLEXISTSXMLTABLE構築でBY VALUEBY REFを受け付けますが、無視します。 xmlデータ型は連続した文字列表現を持ちますので、保持されるノードIDは無く、引き渡しは実際には常にBY VALUEです。

D.3.2.2. 問い合わせに名前付きパラメータは渡せない #

XPathベースの関数はXPath式のコンテキスト要素として働くようにパラメータを渡すことをサポートしていますが、名前付きパラメータの式にできるように追加値を渡すことはサポートしていません。

D.3.2.3. XML(SEQUENCE)型は無い #

PostgreSQLxmlデータ型はDOCUMENTまたはCONTENT形式でのみ値を保持できます。 XQuery/XPath式コンテキストの要素は単独のXMLノードか原子値でなければなりません。しかし、XPath 1.0ではさらにXMLノードのみに制限していて、加えてCONTENTが可能なノードタイプを持ちません。 結果として、整形式のDOCUMENTのみが、PostgreSQLでXPathコンテキストの要素として提供されるXML値の形式です。