PostgreSQLのXML機能解説
2010年10月01日作成
安部 みのぶ
PostgreSQLとは、オープンソースのリレーショナルデータベースである。LINUX、Windows、Mac OS X、SolarisなどのOS上で動作する。
XMLのサポートの経緯について少しふれると、2002年2月にバージョン7.2で、初めてXML拡張モジュールが導入され、2005年1月にバージョン8.0でXPath機能とXSLT機能をサポートするXML2モジュールが追加された。そして、2008年2月リリースのバージョン8.3から標準機能としてXMLデータ型やXPath機能がサポートされるようになった。2010年8月現在のPostgreSQLはバージョン8.4.4(2010.5.17リリース)であるが、XML機能は8.3と同じ内容である。XSLT機能の標準機能でのサポート、XMLSchema対応などが今後、サポート、標準機能としてのサポートが期待される分野である。特に、XSLT機能をサポートするxml2モジュールは将来的に削除される予定であるとPostgreSQLの技術文書の中に記載されている。
本稿では、PostgreSQLが標準、および追加モジュールとしてサポートしている、XML関連の機能を大まかに分類し、それぞれ解説する。PostgreSQLは8.4.1を使用した。
- 1. XMLデータ型サポート
- 2. XPathによる検索
- 3. GINインデックス
- 4. RDBからXMLを生成するSQL/XML
- 5. 名前空間
- 6. XSLT機能(追加モジュール)
なお、本稿ではコマンド・プロンプトで実行できる、対話式プログラムのpsqlツールを使用した。
1.XMLデータ型サポート
PostgreSQL8.3以降、標準機能としてXMLデータ型のサポートが開始されたことにより、textやintegerなどのデータ型のひとつとしてXML型を使用できるようになった。データベースにテーブルを作成するときにSQL文を使って、以下のようにテーブルを定義できるということを意味する。
CREATE TABLE magazine(title text, writer text,word_count integer, article xml);
この例では、magazineテーブルを作成し、title列(テキスト型)、writer列(テキスト型)、word-count列(integer型)、article列(XML型)を定義している。
実際にXML型でデータを格納するにはいくつかの方法が考えられる。まずは、もっとも単純な方法として、SQLのINSERT文の中に直接タグを書く方法がある。
INSERT INTO magazine(title, writer, word_count, article) VALUES(‘PostgreSQL and Usage’,’John Smith’,15000,’
<?xml version="1.0" encoding="Shift_JIS" ?> <article> <title1>ポストグレスの利用方法</title1> <title2>家庭にて</title2> <description>ポストグレスはデータベースです。ご家庭では…</paragraph> </description></article>’);
しかし、上の例でもわかるようにXMLデータは通常のRDBのデータとくらべて長くなるため、すべて手入力するのは冗長になり、いささか現実的でない。
それで、大量のデータをテーブルに一括格納するために、copyコマンドを使って以下のようにCSVファイルから読み込むことができる。
COPY magazine FROM 'C:/pgsqlxml/magtable002.csv' WITH CSV;
magtable002.csv
"Uninstall from Machine","Junko Ishikawa",2300,"<?xml version=""1.0"" encoding=""Shift_JIS"" ?> <article><title1>アンインストール手順</title1> <title2>Windows XPにて</title2> <description><paragraph>スタートボタンをクリックして、コントロールパネルを・・・</paragraph> </description><title2>Linuxにて</title2> <description><paragraph>ターミナルからrpmコマンドを実行します</paragraph> </description></article>"
また、RDBのデータは手入力し、XMLデータ列だけを別ファイルから読み込むには、psqlの変数差し替え機能を利用できる。これは、変数にファイルの内容を展開して代入しておき、INSERT文で通常通りデータを格納するときにXMLデータ列に変数を指定するという方法である。
\set foo ''''`type C:\pgsqlxml\article03.xml`'''' insert into magazine(title,writer,word_count,article) values(‘Connect to Postgres’,’Minobu Abe’,3000,:foo);
article03.xml(変数fooに代入するファイル)
<?xml version="1.0" encoding="Shift_JIS" ?><article><title1>ポストグレスへの接続</title1> <title2>psqlを使って</title2> <description><paragraph>接続にはコマンドプロンプトを使います。そして、・・・</paragraph> </description></article>
以上、3つの方法でテーブルに格納したデータを確認すると以下のような結果が得られるはずである。
testdb=# select * from magazine;
title | writer | word_count | article
------------------------+----------------+------------+------------------------------------------
PostgreSQL and Usage | John Smith | 15000 | <article> <title1>ポストグレスの利用方法</title1> <title2>家庭にて</title2> <description> <paragraph>ポストグレスはデータベースです。ご家庭では…</paragraph> </description></article>
Uninstall from Machine | Junko Ishikawa | 2300 | \r
: <article>\r
: <title1>アンインストール手順</title1>\
: <title2>Windows XPにて</title2>\r
: <description>\r
: <paragraph>スタートボタンをクリックして、
: コントロールパネルを・・・</paragraph>\r
: </description>\r
: <title2>Linuxにて</title2>\r
: <description>\r
: <paragraph>ターミナルからrpmコマンドを
: 実行します</paragraph>\r
: </description>\r
: </article>
Connect to Postgres | Minobu Abe | 3000 | \r
: <article>\r
: <title1>ポストグレスへの接続</title1>\r
: <title2>psqlを使って</title2>\r
: <description>\r
: <paragraph>接続にはコマンドプロンプトを
: 使います。そして、・・・</paragraph>\r
: </description>\r
: </article>
(3 rows)
なお、XML型として定義した列にXMLデータを格納するときに、XMLがきちんと書かれているか(開始タグと終了タグの対応がとれているか、つまりWell-formedか)がPostgreSQLによってチェックされる。問題のある場合は、以下のようなエラーが表示され、データを格納することができない。
ERROR: invalid XML content
XML Schemaによるチェック/検証を行う機能は、現在のところPostgreSQL本体にも、追加モジュールにも用意されていない。ApachプロジェクトによるXERCESなど、既存のスキーマ検証プロセッサを利用して別途対応が必要となる。
2.XPathによる検索
XPathとは、XMLデータ型として定義した列に格納したXMLデータの、特定の部分を取り出すため、様々な条件を付加しデータ内部にアクセスするための規格である。PostgreSQLでは8.3から標準機能としてXPath式の評価機能が追加された。単なるテキスト“検索”とは違い、XPathを使った検索では、階層構造を持つXMLデータの構造を利用し、特定の位置指定と値の検索とを組み合わせた検索を実現できる。
また、XSLT機能を使ってXMLデータの特定の部分を加工したり、構造変換したりするにはXPathによる指定が不可欠である。XSLT機能自体は現在、追加モジュールの形で提供されている。この機能については、「6.XSLT機能(追加モジュール)」で後述する。
ここでは、XPathの概要と、XPathをPostgreSQL上で使う方法について説明する。 Xpathでは、XMLをツリー構造モデルとしてみたときの起点(現在地点)から13種類の方向を指定することができる。(図1)
それぞれの方向にはchild(子)やdescendant(子孫)といった名前が付いており、その名前を明記して方向を定める(省略した書き方も用意されている)。さらに、要素名を指定したり、式を使って特定の値や属性値を含むものを抽出したりできる。式の中で使える関数も用意されている。これらを組み合わせて使うことにより、自由自在に望む結果を得ることができる。以下は、その一例である。
これは、「『ポストグレス』という文字列を含むtitle1要素を子に持つarticle要素の子要素であるtitle1要素」を指すXPath式である。この中でスラッシュで区切られた部分をロケーションステップという。このロケーションステップの中に次に進むべき方向を示すノードテストや、条件を指定する述語を記述していく。またこの例では、XPath規格で定義されているcontains関数を使い、ある文字列の中に特定の文字列があるかどうか(例では、title1という要素の中に「ポストグレス」という文字列を含むかどうか)をテストしている。そして、このようにXPathのルールに従って記述されたものをXPath式と呼ぶ。
実際にこのXPath式をPostgreSQLで使うには、xpath関数を呼び出し、その中にXPath式を記述する。(図2)
前節(「1.XML型サポート」)で例としてあげたデータがmagazineテーブルに格納されていれば、以下のような結果が得られる。
xpath
-------------------------------------------
{<title1>ポストグレスの利用方法</title1>}
{<title1>ポストグレスへの接続</title1>}
{} (3 rows)
3.GINインデックス
GIN(Generalized Inverted Index)インデックスは、PostgreSQLに用意されている数種類のインデックスのひとつで、日本語では汎用転置インデックスを表す。
インデックスとは通常、検索されそうな値だけを取り出して別途保管しておき、検索時に全体に当たるのではなく、インデックス内を検索することで検索処理を高速化する仕組みである。PostgreSQLでは、XMLデータについても、検索されそうな値をXPathで取り出してインデックスを作成することが可能である。
実際のインデックス作成は図3のように行う。成功すると CREATE INDEX と表示される。
検索するときは、インデックスを作成したときと同じXPath式をSELECT文のWHERE句に書く。たとえば以下のように。
SELECT xpath('/article/title2/text()',article) FROM magazine WHERE (xpath('/article/title2/text()',article)::text[]) @> '{Linuxにて}';
比較演算子は、通常のもの(<、>、=)ではなく、配列型で使用可能な配列演算子と呼ばれる演算子を使う。@>は含むという意味である。
インデックスを使った検索のスピードを検証するには、SELECT文の前に、結果そのもではなく、処理の解析結果が得られる「EXPLAIN ANALYZE」と指定するとよい。
4.RDBからXMLを生成する
SQL/XML 次にリレーショナルデータとして格納されているデータからXMLを生成するSQL/XMLの機能について説明する。 SQL/XML機能とは、ISOのSQL:2003標準のうちXML関連の機能(ISO/IEC 9075-14 XML-related specifications (SQL/XML) ) のことを指す。ISOのバージョン(2003年版、2006年版等)によって機能の拡張や修正が行われており、データベースによっても実装にはばらつきがある。PostgreSQLでは、SQL/XMLのXML型の値を生成する関数として、XMLCONCAT、XMLELEMENT(XMLATTRIBUTESを含む)、XMLFOREST、XMLCOMMENT、XMLROOT、XMLPI、 および、xml型から他の型への変換を行う関数として XMLPARSE、XMLSERIALIZE, そして集約関数であるXMLAGG関数が用意されている。
この機能を利用して、magazineテーブルのtitle列(記事のタイトル)とwriter列(著者名)の値を取り出し、XMLとして有効な文書を作成するSQL文は以下のとおりである。
select xmlroot(xmlelement(name title_list,
(select xmlagg(
xmlelement(name list,
xmlelement(name title, title),
xmlelement(name writer, writer)
)) from magazine)),version '1.0',standalone yes);
上のSELECT文では、要素名と、参照する列名を指定してXML要素を生成するxmlelement関数の他に、バージョン情報などを指定してルート要素を作成するxmlroot関数等も使用している。XMLの階層構造は、xmlelement関数を入れ子にして記述していくことで表現できる。xmlelement関数は、引数に指定したテキストを値として要素を1つづつ生成する関数だが、要素の値に列名を指定することによってテーブルからデータを取得してXMLの要素とすることができる。また、select文自体を入れ子(サブクエリー)にすることで、外側のSELECT文が1回だけ実行される間に、内部のSELECT文が行ごとに繰り返され、全体としては、すべての該当する行のデータを取り出したのち1つルートを持つXML文書を生成する処理となっている。
これを実行すると、以下のようなXML文書が生成される。
<?xml version="1.0" standalone="yes"?>
<title_list>
<list>
<title>PostgreSQL and Usage</title>
<writer>John Smith</writer>
</list>
<list>
<title>Connect to Postgres</title>
<writer>Minobu Abe</writer>
</list>
合わせて、psqlのヘッダー/フッター非表示オプション(\t)や、ファイルへの出力指定(\o ‘出力ファイル’)を使えば、RDBの内容を一発でXMLファイルとして出力することができ、非常に便利である。
5.名前空間対応
実際のXMLの利用では名前空間接頭辞をつけて要素名を表現することが多い。これは、一つのXMLの中で複数のXMLSchemaで定義された要素が競合することなく共存するためである。PostgreSQLではXMLSchemaを使った検証には対応していないが、名前空間接頭辞つきのXMLデータを扱うための仕組みが準備されている。それはxpath関数の3番目の引数(オプション)である。
xpath関数の構文は、「xpath(xpath,xml[,nsarray])」となっておりnsarryは、名前空間マッピング配列である。以下のように2次元配列を構築し、その中で名前空間接頭辞と名前空間のURIを対応付けて用いる。
xpath('/a:article/a:title1/text()', article,array[array['a','http://www.potgresql.jp/schema/article']]
ここで対応付ける名前空間接頭辞は、実際にXMLデータの中で使われている名前空間接頭辞と同じでなくても、名前空間URIさえ同じであれば望むデータを取り出すことができる。
6.XSLT機能(追加モジュール)
XSLTはXMLデータの構造変換を行う方法を定めたW3Cによる規格である。XMLからXMLへの構造変換はもちろんのこと、XMLからHTML(タグの省略をしないXHTML)への変換にも使える。XSLTによる構造変換では、元のXMLデータ(ソースツリーと呼ぶ)からどのような結果(結果ツリーと呼ぶ)を生成するかを、スタイルシートに記述しておき、XSLTの規格を実装したXSLTプロセッサと呼ばれるプログラムで、ソースツリーとスタイルシートを読み込んで処理を行う。PostgreSQLではこのXSLTプロセッサは、xml2追加モジュールとして提供されている。これはデフォルトではインストールされないが、PostgreSQLのインストールフォルダからpgxml.sqlファイルを探し、そこに用意されているクエリを実行することで利用可能になる。psqlコンソールからインストールするには以下のコマンドを実行する。
\i 'C:/Program Files/PostgreSQL/8.3/share/contrib/pgxml.sql'
結果として、SETおよび14行のCREATE FANCTIONが表示されれば正しくインストールされており、利用可能な状態になっている。
xslt機能の呼び出しは、xslt_process関数で行う。xslt_process関数の構文は、「xslt_process(document, stylesheet)」である。この引数はテキスト型であるため、それぞれxslt_process関数に引き渡す際に、テキスト型へ変換する必要がある。図4のように指定できる。返される結果もテキスト型となる。
まとめ
以上、XMLデータ型サポート、XMLの階層構造をたどるXPath機能、名前空間やXSLT構造変換機能、さらにはリレーショナルデータを基にXMLデータを生成するSQL/XML機能など、PostgreSQLがXMLをしっかりサポートしていることを確認できた。大手ベンダーによるRDBMSと比べても遜色ない。今後はXMLSchemaのサポートや、XSLT機能の本体での実装が待たれるところである。
参考URL:
■ http://www.postgresql.jp/ 日本PostgreSQLユーザ会(PostgreSQL本体、日本語マニュアルを入手可能)
■ http://archives.postgresql.org/pgsql-hackers/ 本家アメリカのPostgreSQL開発者メーリングリスト(バグや新機能についての議論も行われている)