23 OCIでのXMLのサポート

Oracle XML DBでは、XMLTypeデータ型を使用したXMLインスタンスの格納および操作をサポートしています。これらのXMLインスタンスにアクセスするには、OCIをC DOM API for XMLと併用します。

アプリケーション・プログラムでは、サーバー・ハンドル、文ハンドルなどの通常のOCIハンドルを初期化し、その後XMLコンテキストを初期化する必要があります。アプリケーション・プログラムでは、バックエンドでXMLインスタンスを操作したり、クライアント側で新規インスタンスを作成できます。初期化されたXMLコンテキストは、すべてのC DOM関数で使用できます。

Oracle XML DBに格納されたXMLデータは、C DOM構造体xmldocnodeによってクライアント側でアクセスできます。この構造体は、OCI文のXML値のバインド、定義および操作に使用できます。

関連項目:

23.1 XMLコンテキスト

XMLコンテキストは、すべてのC DOM API関数における必須パラメータです。

この不透明なコンテキストは、データ・エンコーディング、エラー・メッセージ言語などに関する情報をカプセル化します。このコンテキストの内容は、XDKおよびOracle XML DBアプリケーションでは異なります。

Oracle XML DBの場合、XMLコンテキストを初期化および解放するための2つのOCI関数が提供されています。

xmlctx *OCIXmlDbInitXmlCtx (OCIEnv *envhp, OCISvcCtx *svchp, OCIError *errhp,
       ocixmldbparam *params, ub4 num_params);

void OCIXmlDbFreeXmlCtx (xmlctx *xctx);

23.2 サーバー上のXMLデータ

サーバー上のXMLデータは、OCI文のコールによって操作できます。他のオブジェクト・インスタンスと同様に、xmldocnodeを使用してXMLTypeの値をバインドおよび定義できます。

サーバーからXMLデータを選択するには、OCI文を使用します。このデータは直接C DOM関数で使用できます。同様に、値を直接SQL文にバインドしなおすことができます。

23.3 OCI XML DB関数の使用

XMLコンテキストを初期化および終了するには、それぞれOCIXmlDbInitXmlCtx()関数およびOCIXmlDbFreeXmlCtx()関数を使用します。

ヘッダー・ファイルocixmldb.hは統合C APIとともに使用されます。

例23-1は、C APIによる操作の実行方法を示すテスト例のコード・フラグメントです。

例23-1 C APIによるXMLコンテキストの初期化および終了

#ifndef S_ORACLE
#include <s.h>
#endif
#ifndef ORATYPES_ORACLE
#include <oratypes.h>
#endif
#ifndef XML_ORACLE
#include <xml.h>
#endif
#ifndef OCIXML_ORACLE
#include <ocixmldb.h>
#endif
#ifndef OCI_ORACLE
#include <oci.h>
#endif
#include <string.h>

typedef struct test_ctx {
        OCIEnv *envhp;
        OCIError *errhp;
        OCISvcCtx *svchp;
        OCIStmt *stmthp;
        OCIServer *srvhp;
        OCIDuration dur;
        OCISession *sesshp;
        oratext *username;
        oratext *password;
} test_ctx;

...
void main()
{
  test_ctx temp_ctx;
  test_ctx *ctx = &temp_ctx;
  OCIType *xmltdo = (OCIType *) 0;
  xmldocnode *doc = (xmldocnode *)0;
  ocixmldbparam params[1];
  xmlnode *quux, *foo, *foo_data, *top;
  xmlerr err;
  sword status = 0;
  xmlctx *xctx;
 ...
  /* Initialize envhp, svchp, errhp, dur, stmthp */
  ...
 
  /* Get an xml context */
  params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
  params[0].value_ocixmldbparam = &ctx->dur;
  xctx = OCIXmlDbInitXmlCtx(ctx->envhp, ctx->svchp, ctx->errhp, params, 1);

/* Do unified C API operations next */
...

/* Free the statement handle using OCIHandleFree() */
...
/* Free the allocations associated with the context */
OCIXmlDbFreeXmlCtx(xctx);
/* Free envhp, svchp, errhp, stmthp */
...
}

23.4 OCIクライアントからバイナリXMLへのアクセス

中間層とクライアント層では、バイナリのXML形式でXMLを生成、消費および処理できます。

Cアプリケーションでは、XML DBリポジトリからデータをフェッチし、DOMを使用してXMLの更新を実行し、データベースに格納します。または、クライアント上で作成または入力されたXML文書に対して、XSLT、XQueryおよび他のユーティリティを使用できます。その後、出力XMLはXML DBに保存されます。

クライアント・アプリケーションは、バイナリのXML文書のエンコードまたはデコード中にトークン定義、XMLスキーマおよびDTDをフェッチするために、メタデータ・リポジトリ(通常はバックエンド・データベース)への接続(メタデータ接続)を必要とします。

リポジトリ・コンテキストは、専用接続または接続プールを使用して初期化されます。リポジトリ・コンテキストから取得した接続を使用して、トークン定義やXMLスキーマなどのメタデータがフェッチされます。これに対して、アプリケーションには、データベースとの間でデータ(XMLデータなど)の通常の転送に使用するデータ接続もあります。リポジトリ・コンテキストは、(1つ以上の)データ接続に明示的に関連付けられています。データ接続を使用してデータベースとの間でXMLデータが読書きされる場合、基礎となるエンコードまたはデコード操作中に、該当するリポジトリ・コンテキストがアクセスされます。必要に応じて、リポジトリからメタデータをフェッチするためにメタデータ接続が使用されます。

23.4.1 OCIアプリケーションからXMLデータへのアクセス

Cアプリケーションでは、OCIを使用してデータベースに存在する永続XMLにアクセスし、統合XML C APIを使用してフェッチしたXMLデータを操作できます。

クライアント・アプリケーションでは、次のステップを実行します。

  1. 通常のOCIハンドル(OCIEnvOCISvcCtxおよびOCIErrorなど)を作成します。
  2. バイナリのXMLメタデータをフェッチするためにリポジトリ・コンテキストを1つ以上作成します。
  3. リポジトリ・コンテキストをデータ接続に関連付けます。
  4. 変数をSELECT、INSERTおよびUPDATE文にバインドまたは定義します(xmldocnode)。
  5. SELECT、INSERTまたはUPDATE文を実行して、XML文書をフェッチまたは格納します。この時点で、クライアントOCIライブラリがデータベース・バックエンドと相互作用し、必要なXMLスキーマ、DTD、トークン定義などをフェッチします。
  6. 統合C APIを使用してXMLデータ(DOM)を操作します。

23.4.2 リポジトリ・コンテキスト

OCIBinXmlReposCtxは、リポジトリ・コンテキストのデータ構造です。

クライアント・アプリケーションでは、メタデータ・リポジトリに接続情報を提供することで、このコンテキストを作成します。アプリケーションでは、複数のリポジトリ・コンテキストを作成して複数のトークン・リポジトリに接続できます。リポジトリ・コンテキストは、データ接続(OCISvcCtx)に明示的に関連付けられます。システムがデータ接続との間でデータをエンコードまたはデコードするためにメタデータをフェッチする必要がある場合は、該当するメタデータにアクセスします。

アプリケーションでは、OCIEnvごとに1つリポジトリ・コンテキストを作成することをお薦めします。これにより、マルチスレッド・アプリケーションの同時実行性が向上します。

リポジトリ・コンテキストは、専用OCI接続またはOCI接続プールから作成できます。

23.4.3 専用OCI接続からのリポジトリ・コンテキストの作成

OCIBinXmlCreateReposCtxFromConn()は、指定した専用OCI接続を使用してリポジトリ・コンテキストを作成します。

OCI接続はメタデータ・アクセスでのみ使用されるため、アプリケーションの別のシナリオでは使用しないでください。また、この接続へのアクセスはシリアライズされています。つまり、複数のスレッドが同じ接続を使用しようとしている場合、アクセスは一度に1つのスレッドに制限されます。次の項で説明するように、スケーラビリティの理由により、アプリケーションでは接続プールを使用してリポジトリ・コンテキストを作成することをお薦めします。

ノート: データに使用するのと同じ接続を渡すことも可能です。ただし、この場合、クライアント・システムがSELECTやINSERTのような別の操作の一部を実行する間にメタデータ・リポジトリに接続すると、特定の状況でエラーになる可能性があります。

23.4.4 接続プールからのリポジトリ・コンテキストの作成

OCIBinXmlCreateReposCtxFromCPool()では、接続プールからリポジトリ・コンテキストが作成されます。

アプリケーションからバックエンド・リポジトリにアクセスする間に、プール内の使用可能接続が使用されます。さらに、この接続はメタデータ操作の完了直後にプールに解放されます。マルチスレッド・アプリケーションのシナリオには、接続プールを使用することをお薦めします。様々なスレッドがプール内の異なる接続を使用し、完了直後に解放できます。このアプローチでは、少数の物理接続で高度な拡張性と同時実行性が実現できます。

23.4.5 リポジトリ・コンテキストとデータ接続の関連付けについて

OCIBinXmlSetReposCtxForConn()では、リポジトリ・コンテキストがOCISvcCtx *により記述されたデータ接続に関連付けられます。

複数のデータ接続で同じリポジトリ・コンテキストを共有できますが、リポジトリへのアクセスがシリアル化される可能性があります(専用接続ベースの場合)。システムがエンコードまたはデコード操作のためにメタデータをフェッチする必要がある場合は、OCIEnvOCISvcCtxのペアから該当するリポジトリ接続を参照し、それを使用して必要なメタデータをフェッチします。

23.4.6 XMLTypeエンコーディング形式のプリファレンス設定について

デフォルトでは、データベースに送信されたXMLデータは、ソース形式(DBから読取り済の場合)などの特定の内部基準に基づいて、可能な形式(テキスト、オブジェクト・リレーショナルまたはバイナリのXML)のいずれかでエンコードされます。OCIBinXmlSetFormatPref()は、エンコーディング形式のプリファレンスを設定する明示的なメカニズムを提供します。将来は、デフォルト形式をバイナリのXMLにできるようになりますが、この関数を使用すると必要に応じてデフォルト形式を上書きできます。

関連項目:

OCIBinXmlSetFormatPref()

23.4.7 接続プールの使用例

XML DBのマニュアルに示したこの例で、接続プールからリポジトリ・コンテキストを作成してデータ接続に関連付ける方法を示します。

データベースはローカルで、テストは単一スレッド・モードで実行されます。

関連項目:

Oracle XML DBによるXML用OCIおよびC APIの使用方法の詳細は、『Oracle XML DB開発者ガイド』を参照してください