OLE (オブジェクトのリンクと埋め込み) オートメーションは、 Microsoft Corporation の OLE 2.0 アーキテクチャーの一部です。 OLE オートメーションがあれば、ユーザー・アプリケーションは、作成に使用する言語に関係なく、 OLE オートメーション・オブジェクト内でその特性と方式を呈示できます。 Lotus Notes や Microsoft Exchange(R) のような他のアプリケーションは、OLE オートメーションによるこれらの特性と方式を利用して、これらのオブジェクトを統合することができます。
これらの特性と方式を呈示するアプリケーションを OLE オートメーション・サーバーまたはオブジェクトと呼び、それらにアクセスするアプリケーションを OLE オートメーション・コントローラーと呼びます。 OLE オートメーション・サーバーは、 OLE IDispatch インターフェースをインプリメントする COM 構成要素 (オブジェクト) です。 OLE オートメーション・コントローラーは、サーバーの IDispatch インターフェースを介してオートメーション・サーバーと通信する COM クライアントです。 COM (Component Object Model; 構成要素オブジェクト・モデル) は、OLE の土台をなすものです。 OLE オートメーション UDF の場合、DB2 は OLE オートメーション・コントローラーとして動作します。 DB2 は、この機構を介して、OLE オートメーション・オブジェクトの方式を外部 UDF として呼び出すことができます。
この項では、読者が OLE オートメーションに関する用語や概念に精通していることを前提としています。本書では、OLE の初歩的な説明は行いません。 OLE オートメーションの概説については、 Microsoft Corporation: The Component Object Model Specification (1995 年 10 月) を参照してください。 OLE オートメーションの詳細については、 OLE Automation Programmer's Reference (Microsoft Press、1996 年、ISBN 1-55615-851-3) を参照してください。
OLE オートメーション UDF を例示する、 DB2 アプリケーション開発クライアントに組み込まれたサンプル・アプリケーションのリストについては、 表 49 を参照してください。
OLE オートメーション UDF は、 OLE オートメーション・オブジェクトのパブリック・メソッドとしてインプリメントされています。 OLE オートメーション・オブジェクトは、 OLE オートメーション・コントローラー (この場合は DB2) によって外部で作成可能でなければならず、遅延バインド (IDispatch ベースのバインドとも呼ばれる) をサポートしなければなりません。 OLE オートメーション・オブジェクトは、クラス識別子 (CLSID) および任意で OLE プログラム ID (progID) を指定して、 Windows 登録データベース (レジストリー) に登録し、オートメーション・オブジェクトを識別するようにします。 progID は、プロセス内 (.DLL) またはローカル (.EXE) OLE オートメーション・サーバー、または DCOM (分散 COM) を介してリモート・サーバーを識別できます。 OLE オートメーション UDF は、スカラー関数か表関数のいずれかです。
OLE オートメーション・オブジェクトのコード化が終わったら、 SQL CREATE FUNCTION ステートメントを使用して、そのオブジェクトのメソッドを UDF として登録する必要があります。 OLE オートメーション UDF の登録は、 C または C++ の外部 UDF の登録と非常に類似していますが、以下のオプションを使用する必要があります。
外部名は、OLE 自動化オブジェクトを識別する OLE progID とメソッド名を ! (感嘆符) で区切った形になります。
CREATE FUNCTION bcounter () RETURNS INTEGER EXTERNAL NAME 'bert.bcounter!increment' LANGUAGE OLE FENCED SCRATCHPAD FINAL CALL NOT DETERMINISTIC NULL CALL PARAMETER STYLE DB2SQL NO SQL NO EXTERNAL ACTION DISALLOW PARALLEL;
OLE メソッド・インプリメンテーションの呼び出し規則は、 C や C++ で作成された関数の呼び出し規則と同一です。上記のメソッドを BASIC 言語でインプリメントすると、次のようになります (BASIC では、パラメーターは省略時設定で参照呼び出しとして定義されることに注意してください)。
Public Sub increment(output As Long, _ indicator As Integer, _ sqlstate As String, _ fname As String, _ fspecname As String, _ sqlmsg As String, _ scratchpad() As Byte, _ calltype As Long)
OLE オートメーション UDF (OLE オートメーション・オブジェクトの方式) は、 OLE オートメーション・オブジェクトのインスタンス上で適用されます。 DB2 は、SQL ステートメント内で UDF を照会するたびにオブジェクト・インスタンスを作成します。オブジェクト・インスタンスは SQL ステートメント内でそれ以後の UDF 参照の方式呼び出しに再使用されます。つまり、方式呼び出しの後にインスタンスは解放され、それ以後の方式呼び出しのたびに新しいオブジェクトが作成されます。 SQL CREATE FUNCTION ステートメントの SCRATCHPAD オプションによって、適切な振る舞いを指定できます。 LANGUAGE OLE 文節の場合、SCRATCHPAD オプションには C や C++ の場合よりも多くの意味があり、 1 つのオブジェクト・インスタンスが 1 つの照会を通じて使用するために作成および再利用されますが、NO SCRATCHPAD が指定されている場合には、メソッドが呼び出されるたびに新しいオブジェクト・インスタンスが作成されます。 SQL ステートメント内で UDF が参照されるたびに、個々のインスタンスが作成されます。
スクラッチパッドを使用すると、メソッドは複数の関数呼び出しにわたって状態情報をオブジェクトのインスタンス変数内に保持できます。また、オブジェクト・インスタンスは 1 度だけ作成され、後の呼び出しで再利用されるので、パフォーマンスも向上します。
DB2 は、SQL タイプと OLE オートメーション・タイプの間でタイプ変換を処理します。次の表では、サポートされるデータ・タイプと、それらがどのようにマップされるかを要約しています。
OLE オートメーション・タイプから BASIC や C/C++ などのインプリメント用プログラミング言語へのマッピングについては、
表 17 で説明しています。
表 16. SQL と OLE オートメーション・データ・タイプのマッピング
SQL タイプ | OLE オートメーション・タイプ | OLE オートメーション・タイプの説明 | ||
---|---|---|---|---|
SMALLINT | short | 16 ビットの符号付き整数 | ||
INTEGER | long | 32 ビットの符号付き整数 | ||
REAL | float | 32 ビットの IEEE 浮動小数点数 | ||
FLOAT または DOUBLE | double | 64 ビットの IEEE 浮動小数点数 | ||
DATE | DATE | 1899 年 12 月 30 日からの日数を表す、64 ビットの浮動小数点分数 | ||
TIME | DATE | |||
TIMESTAMP | DATE | |||
CHAR(n) | BSTR | OLE Automation Programmer's Reference で説明されている、長さフィールド付ストリング | ||
VARCHAR(n) | BSTR | |||
LONG VARCHAR | BSTR | |||
CLOB(n) | BSTR | |||
GRAPHIC(n) | BSTR | OLE Automation Programmer's Reference で説明されている、長さフィールド付ストリング | ||
VARGRAPHIC(n) | BSTR | |||
LONG GRAPHIC | BSTR | |||
DBCLOB(n) | BSTR | |||
CHAR(n)1 | SAFEARRAY[unsigned char] | 8 バイト無符号データ項目の 1 次元 Byte() 配列。 (SAFEARRAY については、 OLE Automation Programmer's Reference で解説されています。) | ||
VARCHAR(n)1 | SAFEARRAY[unsigned char] | |||
LONG VARCHAR1 | SAFEARRAY[unsigned char] | |||
BLOB(n) | SAFEARRAY[unsigned char] | |||
|
DB2 と OLE オートメーション UDF の間で受け渡しされるデータは、参照呼び出しとして受け渡しされます。表に載っていない、BIGINT、DECIMAL、 LOCATORS などの SQL タイプ、ブール (Boolean) や CURRENCY などの OLE オートメーション・タイプは、サポートされません。 BSTR にマップされる文字とグラフィック・データは、データベース・コード・ページから UCS-2 (Unicode としても知られている、 IBM コード・ページ 13488) スキーマに変換されます。戻される際に、データはデータベース・コード・ページに変換し直されます。これらの変換は、データベース・コード・ページに関係なく起こります。データベース・コード・ページから UCS-2 に、および UCS-2 からデータベース・コード・ページに変換するコード・ページ変換テーブルがインストールされていない場合、 SQLCODE -332 (SQLSTATE 57017) を受け取ります。
OLE オートメーション UDF は、どの言語でもインプリメントできます。この項では、2 つの言語 BASIC や C++ を例として取り上げ、 OLE オートメーション UDF をインプリメントする方法を示します。
表 17 では、様々な SQL データ・タイプから中間の OLE オートメーション・データ・タイプへのマッピング、および目的の言語 (BASIC または C++) のデータ・タイプへのマッピングを示しています。
OLE データ・タイプは言語に依存しません (つまり、
表 16 の内容は、すべての言語にあてはまります)。
表 17. SQL および OLE データ・タイプから BASIC および C++ データ・タイプへのマッピング
SQL タイプ | OLE オートメーション・タイプ | UDF 言語 | |||
---|---|---|---|---|---|
BASIC タイプ | C++ タイプ | ||||
SMALLINT | short | Integer | short | ||
INTEGER | long | Long | long | ||
REAL | float | Single | float | ||
FLOAT または DOUBLE | double | Double | double | ||
DATE、TIME、TIMESTAMP | DATE | Date | DATE | ||
CHAR(n)、VARCHAR(n)、 LONG VARCHAR、CLOB(n) | BSTR | String | BSTR | ||
GRAPHIC(n)、VARGRAPHIC(n)、 LONG GRAPHIC、DBCLOB(n) | BSTR | String | BSTR | ||
CHAR(n)1、 VARCHAR(n)1、 LONG VARCHAR1、 BLOB(n) | SAFEARRAY[unsigned char] | Byte() | SAFEARRAY | ||
|
BASIC で OLE オートメーション UDF をインプリメントするには、 OLE オートメーション・タイプにマップされる SQL データ・タイプに対応している BASIC データ・タイプを使用する必要があります。
OLE オートメーション UDF の作成と登録の bcounter OLE オートメーション UDF を BASIC で宣言すると、次のようになります。
Public Sub increment(output As Long, _ indicator As Integer, _ sqlstate As String, _ fname As String, _ fspecname As String, _ sqlmsg As String, _ scratchpad() As Byte, _ calltype As Long)
OLE 表オートメーションの例は、例: BASIC でのメール OLE オートメーション表関数にあります。
表 17 では、SQL データ・タイプに対応する C++ データ・タイプと、それらがどのように OLE オートメーション・タイプにマップされるかを示しています。
increment OLE オートメーション UDF を C++ で宣言すると、次のようになります。
STDMETHODIMP Ccounter::increment (long *output, short *indicator, BSTR *sqlstate, BSTR *fname, BSTR *fspecname, BSTR *sqlmsg, SAFEARRAY **scratchpad, long *calltype );
OLE は、OLE オートメーション・オブジェクトの特性とメソッドを記述するタイプ・ライブラリーをサポートします。呈示されるオブジェクト、特性、およびメソッドは、オブジェクト記述言語 (ODL) で記述されます。上記の C++ メソッドを ODL で記述すると、次のようになります。
HRESULT increment ([out] long *output, [out] short *indicator, [out] BSTR *sqlstate, [in] BSTR *fname, [in] BSTR *fspecname, [out] BSTR *sqlmsg, [in,out] SAFEARRAY (unsigned char) *scratchpad, [in] long *calltype);
ODL の記述では、パラメーターを入力 (in)、出力 (out)、入出力 (in,out) パラメーターのどれにするかを指定できます。 OLE オートメーション UDF の場合、 UDF 入力パラメーターとその入力標識は [in] パラメーターとして指定され、 UDF 出力パラメーターとその出力標識は [out] パラメーターとして指定されます。 UDF 後書き引き数の場合、 sqlstate は [out] パラメーター、関数と関数の特定の名前は [in] パラメーター、スクラッチパッドは [in,out] パラメーター、呼び出しタイプは [in] パラメーターです。
スカラー関数には 1 つの出力パラメーターと出力標識が含まれますが、表関数には、 CREATE FUNCTION ステートメントの RETURN 列の数に対応する複数の出力パラメーターと出力標識が含まれます。
OLE オートメーションは、ストリングを処理する BSTR データ・タイプを定義します。 BSTR は、OLECHAR: typedef OLECHAR *BSTR へのポインターとして定義されます。 BSTR の割り振りおよび解放の際には、 OLE では呼び出される側が参照呼び出しパラメーターとして渡した BSTR を解放してから、参照呼び出しパラメーターに新しい値を割り当てる、という規則が適用されます。この規則は、DB2 と OLE オートメーション UDF に対しては、次に示す意味があります。呼び出される側が SAFEARRAY** として受け取る 1 次元のバイト配列にも、同じ規則が適用されます。
他のすべてのパラメーターは、ポインターとして渡されます。 DB2 は、参照されるメモリーを割り振りおよび管理します。
OLE オートメーションには、 BSTR と SAFEARRAY を扱うための一そろいのデータ操作関数が備わっています。データ操作関数については、 OLE Automation Programmer's Reference で説明されています。
次の C++ UDF は、CLOB 入力パラメーターの最初の 5 文字を戻します。
// UDF DDL: CREATE FUNCTION crunch (clob(5k)) RETURNS char(5) STDMETHODIMP Cobj::crunch (BSTR *in, // CLOB(5K) BSTR *out, // CHAR(5) short *indicator1, // input indicator short *indicator2, // output indicator BSTR *sqlstate, // pointer to NULL BSTR *fname, // pointer to function name BSTR *fspecname, // pointer to specific name BSTR *msgtext) // pointer to NULL { // Allocate BSTR of 5 characters // and copy 5 characters of input parameter // out is an [out] parameter of type BSTR, that is, // it is a pointer to NULL and the memory does not have to be freed. // DB2 will free the allocated BSTR. *out = SysAllocStringLen (*in, 5); return NOERROR; };
OLE オートメーション・サーバーは、 作成可能単独使用 か、 作成可能複数使用 としてインプリメントできます。作成可能単独使用の場合、 CoGetClassObject で OLE オートメーション・オブジェクトに接続している各クライアント (つまり、 DB2 分離プロセス) は、クラス・ファクトリーの独自インスタンスを使用し、必要に応じて OLE オートメーション・サーバーのコピーを新規に実行します。作成可能複数使用の場合、多数のクライアントが同じクラス・ファクトリーに接続します。つまり、クラス・ファクトリーの各インスタンスは、すでに実行されている OLE サーバー (存在する場合) によって提供されます。実行中の OLE サーバー・コピーがない場合は、自動的に 1 つが起動され、クラス・オブジェクトを提供します。単独使用と複数使用 OLE オートメーションの選択は、オートメーション・サーバーをインプリメントするときにユーザーが行います。パフォーマンスを重視する場合は単独使用サーバーをお勧めします。