SQL:2006でISO/IEC 9075-14 (SQL/XML)のXML関連の仕様についての重要な改定が導入されました。 PostgreSQLのXMLデータ型と関連する関数の実装は、いくつか新しい版から取り入れつつ、主として2003以前の版に従っていました。 特に:
現在の標準は、型付けされていないかXMLスキーマで型付けされている変数で「document」や「content」を格納するXMLのデータ型の一群や、任意のXML内容の断片を格納するXML(SEQUENCE)
型を提供しますが、PostgreSQLは「document」か「content」だけを格納できる単一のxml
型を提供します。
標準の「sequence」型と同等のものはありません。
PostgreSQLはSQL:2006で導入された二つの関数を提供しますが、それらに対して標準で指定されているXML QueryではなくXPath 1.0言語を使う変形としてです。
本章では遭遇するであろういくつかの結果の違いを示します。
PostgreSQL固有の関数xpath()
とxpath_exists()
はXPath言語を使ってXML文書に問い合わせます。
PostgreSQLは、公式にはXQuery言語を使う標準関数のXMLEXISTS
とXMLTABLE
についても、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であるという制限です。
XPathに含まれないXQueryの機能:
XQueryの式は、全てのXPathでできる値に加えて、新たなXMLノードを生成して返すことができます。 XPathは原子型(数値、文字列など)の値を作成して返すことができますが、XMLノードは入力として式に与えられる文書にあらかじめ存在するものしか返せません。
XQueryは構造に対する反復、並べ替え、グループ化の制御ができます。
XQueryでは局所関数を宣言して使用することができます。
最近のXPathバージョンはこれらをカバーする機能(関数形式のfor-each
とsort
、無名関数、文字列からノードを作るparse-xml
など)を提供し始めていますが、これら機能はXPath 3.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つの原子型boolean
、double
、string
のみが使えます。
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 = 7
とsale/@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と等しくできるわけではありません。
SQL:2006以降では、標準SQLデータ型とXMLスキーマ型の間の両方向の変換が正確に明記されています。 しかしながら、その規則はXQuery/XPathの型と意味を用いて説明されていて、XPath1.0の異なるデータモデルへの直接の適用は含まれません。
PostgreSQLがSQLデータの値からXML(xmlelement
で)、あるいは、XMLからSQL(xmltable
の出力列で)に変換するとき、特別扱いされる一部の場合を除いて、PostgreSQLは単純にXMLデータ型のXPath 1.0文字列形式がSQLデータ型のテキスト入力形式として有効であると想定し、逆向きの変換でも同様です。
この規則は多くのデータ型に対して実装が単純という長所を持ち、標準で明記された変換と似た結果になります。
他システムとの相互運用性が重要なところでは、一部のデータ型に対して標準の変換を実現するために明示的に(9.8にあるような)データ型整形関数を使うことがおそらく必要です。
本節はlibxml2ライブラリ固有の制限ではないけれども、PostgreSQLの現在の実装で適用される制限について述べます。
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 REFx
AS a,x
AS b NULL ON EMPTY); SELECT XMLQUERY('$a is $b' PASSING BY VALUEx
AS a,x
AS b NULL ON EMPTY);
PostgreSQLは、XMLEXISTS
やXMLTABLE
構築でBY VALUE
やBY REF
を受け付けますが、無視します。
xml
データ型は連続した文字列表現を持ちますので、保持されるノードIDは無く、引き渡しは実際には常にBY VALUE
です。
XPathベースの関数はXPath式のコンテキスト要素として働くようにパラメータを渡すことをサポートしていますが、名前付きパラメータの式にできるように追加値を渡すことはサポートしていません。
XML(SEQUENCE)
型は無い #
PostgreSQLのxml
データ型はDOCUMENT
またはCONTENT
形式でのみ値を保持できます。
XQuery/XPath式コンテキストの要素は単独のXMLノードか原子値でなければなりません。しかし、XPath 1.0ではさらにXMLノードのみに制限していて、加えてCONTENT
が可能なノードタイプを持ちません。
結果として、整形式のDOCUMENT
のみが、PostgreSQLでXPathコンテキストの要素として提供されるXML値の形式です。