この章では、オブジェクト型トランスレータ(OTT)ユーティリティについて説明します。このユーティリティを使用して、データベース・オブジェクト型、LOB型および名前付きコレクション型をC++クラスの宣言にマッピングし、OCCIアプリケーションで使用できるようにします。
ここでは、次の項目について説明します。
関連項目: この章で使用するデモ・プログラムの完全なコード・リストおよびOTTユーティリティによって生成されるクラスおよびメソッド実装は、$ ORACLE_HOME /rdbms/demo を参照してください。 |
オブジェクト型トランスレータ(OTT)ユーティリティは、Oracleデータベース・サーバーのユーザー定義型を利用するアプリケーションの開発に役立ちます。
オブジェクト型は、SQLのCREATE TYPE
文を使用して作成できます。これらの型の定義はデータベースに格納されており、その後データベース表の作成に使用できます。表が作成されると、OCCIプログラマは表に格納されているオブジェクトにアクセスできます。
オブジェクト・データにアクセスするアプリケーションには、データをホスト言語形式で表現する機能が必要です。この機能は、オブジェクト型クラスをC++で表現することで実現します。
構造体またはクラスを手動でコーディングしてデータベース・オブジェクト型を表現することもできますが、時間がかかり、エラーが発生しやすくなります。OTTユーティリティは、C++に対する適切なクラスを自動的に生成することで、このステップを簡略化します。
OCCIの場合、アプリケーションでは、次のファイルを組み込んでリンクする必要があります。
生成されたクラス宣言が含まれたヘッダー・ファイルを組み込みます。
マッピングを登録する関数のプロトタイプが含まれたヘッダー・ファイルを組み込みます。
オブジェクトをインスタンス化している間にOCCIがコールする静的メソッドが含まれたC++ソース・ファイルとのリンクを設定します。
マッピングを環境に登録する関数が含まれているファイルとのリンクを設定して、この関数をコールします。
データベース型をC++の表現に変換するには、OTTユーティリティを明示的に起動する必要があります。OCCIプログラマでは、マッピングを環境に登録する必要があります。この関数はOTTユーティリティによって生成されます。
ほとんどのオペレーティング・システムでは、コマンドラインからOTTユーティリティを起動します。これは、INTYPE
ファイルを入力として受け取り、OUTTYPE
ファイル、プロトタイプ情報が含まれる1つ以上のC++ヘッダー・ファイルおよび生成されたマッピングを登録する追加C++メソッド・ファイルを生成します。
例8-1 OTTユーティリティの使用方法
次のコマンドはOTTユーティリティを起動し、C++クラスを生成します。OTTはユーザー名demousr
を使用して接続を試行します。システムではパスワードが要求されます。
ott userid=demousr intype=demoin.typ outtype=demoout.typ code=cpp hfile=demo.h cppfile=demo.cpp mapfile=RegisterMappings.cpp
OTTユーティリティでは、demoin.typ
ファイルをINTYPE
ファイルとして使用し、demoout.typ
ファイルをOUTTYPE
ファイルとして使用します。生成された宣言はCODE=cpp
パラメータで指定されたC++でdemo.h
ファイルに出力され、メソッド実装はdemo.cpp
ファイルに出力され、マッピングを登録する関数は、RegisterMappings.h
に出力されたプロトタイプとともに、RegisterMappings.cpp
に出力されます。
OTTユーティリティを使用する最初のステップは、オブジェクト型または名前付きコレクション型を作成してデータベースに格納することです。そのためには、SQLのCREATE TYPE
文を使用します。
例8-2 OTTユーティリティのオブジェクト作成文
CREATE TYPE FULL_NAME AS OBJECT (first_name CHAR(20), last_name CHAR(20)); CREATE TYPE ADDRESS AS OBJECT (state CHAR(20), zip CHAR(20)); CREATE TYPE ADDRESS_TAB AS VARRAY(3) OF REF ADDRESS; CREATE TYPE PERSON AS OBJECT (id NUMBER, name FULL_NAME, curr_addr REF ADDRESS, prev_addr_1 ADDRESS_TAB) NOT FINAL; CREATE TYPE STUDENT UNDER PERSON (school_name CHAR(20));
データベースに型を作成した後の次のステップでは、OTTユーティリティを起動します。
OTTパラメータは、コマンドラインまたは構成ファイルのいずれかで指定できます。一部のパラメータはINTYPE
ファイルでも指定できます。
複数の場所でパラメータを指定した場合には、コマンド・ライン上の値がINTYPE
ファイルでの値よりも優先されます。INTYPE
ファイルでの値がユーザー定義の構成ファイルでの値よりも優先され、ユーザー定義の構成ファイルでの値はデフォルトの構成ファイルでの値よりも優先されます。
したがって、パラメータの優先順位は、次のとおりです。
OTTコマンドライン
INTYPE
ファイルの値
ユーザー定義の構成ファイル
デフォルトの構成ファイル
グローバル・オプション、つまりコマンドラインのオプションまたはINTYPE
ファイルのTYPE
文の前のオプションについては、INTYPE
ファイルの値が上書きされます。(INTYPE
ファイルでグローバル指定できるオプションは、CASE
、INITFILE
、INITFUNC
、MAPFILE
およびMAPFUNC
です。HFILE
またはCPPFILE
は、グローバル指定できません。)INTYPE
ファイルにTYPE
指定で記述されている内容は、特定の型に対してのみ適用され、この特定の型に対して通常適用されるコマンドラインの内容よりも優先されます。したがって、TYPE person HFILE=p.h
を入力すると、その内容はperson
のみに適用され、コマンドラインのHFILE
が上書きされます。この文は、コマンドライン・パラメータとみなされません。
INTYPE
ファイルは、OTTユーティリティで変換する型のリストです。
CASE
、CPPFILE
、HFILE
、INITFILE
、INITFUNC
、MAPFILE
およびMAPFUNC
の各パラメータは、INTYPE
ファイルに指定できます。
構成ファイルは、OTTパラメータが記述されているテキスト・ファイルです。ファイル内の各非空白行には、1つのパラメータと、それに関連付けられた1つ以上の値が含まれています。同じ行に複数のパラメータを指定した場合は、最初のパラメータのみが使用されます。構成ファイルの非空白行では、空白を使用できません。
構成ファイルは、コマンドラインで名前を指定できます。また、デフォルトの構成ファイルは常に読み取られます。このデフォルトの構成ファイルは、常に存在している必要がありますが、空でも構いません。デフォルトの構成ファイルの名前はottcfg.cfg
であり、ファイルの位置はオペレーティング・システム固有の設定です。
関連項目: デフォルトの構成ファイルの位置は、使用しているオペレーティング・システムのマニュアルを参照してください。 |
ほとんどのプラットフォームでは、コマンドラインからOTTユーティリティを起動します。コマンドラインでは特に、入出力ファイルおよびデータベース接続情報を指定できます。
関連項目: オペレーティング・システムでOTTユーティリティを起動する方法は、使用しているオペレーティング・システムのマニュアルを参照してください。 |
例8-3 OTTユーティリティを起動してC++クラスを生成する方法
OTTはユーザー名demousr
を使用して接続を試行します。システムではパスワードが要求されます。
ott userid=demousr intype=demoin.typ outtype=demoout.typ code=cpp hfile=demo.h cppfile=demo.cpp mapfile=RegisterMappings.cpp
注意: OTTコマンドラインの等号(= )の前後には空白を使用できません。 |
OTTコマンドライン文は、コマンドOTTと、その後に続くOTTユーティリティ・パラメータのリストで構成されています。
HFILE
パラメータは、ほとんどの場合に使用されます。省略した場合は、INTYPE
ファイル内の各型に対して、HFILE
を個別に指定する必要があります。OTTユーティリティは、INTYPE
ファイルにリストされていない型の変換が必要であると判断した場合は、エラーをレポートします。したがって、INTYPE
ファイルが以前にOTT OUTTYPE
ファイルとして生成されている場合のみ、HFILE
パラメータを省略できます。
INTYPE
ファイルを省略すると、スキーマ全体が変換されます。詳細は、次の項のパラメータの説明を参照してください。
OTTユーティリティを使用してC++を生成するには、CODE
パラメータをCODE=CPP
に設定する必要があります。CODE=CPP
を指定した場合は、メソッド実装ファイルとマッピング登録関数ファイルのファイル名を定義するために、CPPFILEパラメータ
とMAPFILE
パラメータを指定する必要があります。マッピング関数の名前は、OTTユーティリティによってMAPFILE
から作成するか、MAPFUNC
パラメータを使用して指定できます。また、ATTRACCESS
は、生成したコードの変更を指定できるオプションのパラメータです。これらのパラメータは、C++クラスの生成を制御します。
OTTコマンドラインにパラメータを入力します。この場合、parameter
はリテラル・パラメータ文字列であり、value
は有効なパラメータ設定値です。リテラル・パラメータ文字列は大/小文字を区別しません。
parameter=value
コマンドラインのパラメータは、空白またはタブのいずれかを使用して区切ります。
また、パラメータは構成ファイル内でも指定できます。ただし、この場合、行の中に空白を入れることはできないため、各パラメータは独立した行に指定する必要があります。さらに、CASE
、CPPFILE
、HFILE
、INITFILE
、INTFUNC
、MAPFILE
およびMAPFUNC
の各パラメータは、INTYPE
ファイルに指定できます。
表8-1は、OTTユーティリティのすべてのパラメータを示しています。
表8-1 OTTユーティリティのパラメータの概要
パラメータ | 説明 |
---|---|
|
型属性へのアクセスが |
|
生成されるC++識別子の大/小文字の区別に影響します。 |
|
変換のターゲット言語を指定します。 |
|
共通に使用されるパラメータ指定がリストされるOTT構成ファイルの名前を指定します。 |
|
メソッド実装が書き込まれるC++ソース・ファイルの名前を指定します。 |
|
エラー・メッセージ出力ファイルの名前を指定します。 |
|
生成されたC++クラスが書き込まれるC++のヘッダー・ファイル名を指定します。 |
|
|
|
OTTユーティリティで生成するマッピング・ファイルとそれに対応するヘッダー・ファイルの名前を指定します。 |
|
生成するマッピングの登録に使用する関数の名前を指定します。 |
|
|
|
デフォルト・スキーマに基づいて命名した型のデータベース名の修飾を制御します。 |
|
INTYPEに明示的にリストされていない型の依存性を変換するかどうかを指定します。 |
|
アプリケーションがUTF16をサポートし、 |
|
ユーザーが追加したコードを引き継ぐために、OTTマーカーをサポートする必要があるかどうかを指定します。 |
|
OTTユーティリティが使用するデータベース接続情報を指定します。 |
このパラメータは、型属性へのアクセスを指定します。
PROTECTED
は、デフォルトです。
PRIVATE
の場合、OTTユーティリティにより、get
XXX
()
およびset
XXX
()
のそれぞれの型属性に対して、アクセッサ・メソッドおよびミューテータ・メソッドが生成されます。
このパラメータは、生成されるC++識別子の大/小文字の区別に影響します。CASE
の有効な値は、次のとおりです。
SAME
の場合、データベース型と属性名をC++識別子に変換するときに、文字の大/小文字は変更されません。
LOWER
の場合、大文字はすべて小文字に変換されます。
UPPER
の場合、小文字はすべて大文字に変換されます。
OPPOSITE
の場合、大文字はすべて小文字に変換され、小文字はすべて大文字に変換されます。
このパラメータは、INTYPE
ファイルに記述されていない識別子(明示的にリストされていない属性または型)のみに作用します。大/小文字の変換は、正当な識別子が生成された後で行われます。
INTYPE
ファイルに記述されていない、大/小文字の区別のないSQL識別子は、CASE=SAME
の場合は大文字で、CASE=OPPOSITE
の場合は小文字で表現されます。SQL識別子は、宣言時に引用符が付けられていない場合、大/小文字が区別されません。
このパラメータは、OTTユーティリティで出力するホスト言語を指定します。OCCIアプリケーション用にC++コードを生成するには、CODE=CPP
をOTTユーティリティに指定する必要があります。
このパラメータは、共通に使用されるパラメータ指定がリストされるOTT構成ファイルの名前を指定します。パラメータ指定は、オペレーティング・システム固有の位置にあるシステム構成ファイルからも読み取られます。残りのすべてのパラメータ指定は、コマンドラインまたはINTYPE
ファイルに指定する必要があります。
OTTコマンドラインに指定できるのは、CONFIG
パラメータのみです。これはCONFIG
ファイルに指定できません。
このパラメータは、OTTユーティリティで生成するメソッドの実装が含まれるC++ソース・ファイルの名前を指定します。このファイルで生成されるメソッドは、オブジェクトをインスタンス化するときにOCCIからコールされ、アプリケーション内から直接コールされることはありません。
次の場合、このパラメータは必須です。
INTYPE
ファイルに指定されていない型の生成が必要で、2つ以上のCPPFILE
が生成されている場合。この場合、未指定の型は、コマンドラインに指定したCPPFILE
に格納されます。
INTYPE
パラメータが未指定で、スキーマ内のすべての型をOTTユーティリティで変換する場合。
CPPFILE
パラメータがINTYPE
ファイルの個々の型に対して指定されている場合、このパラメータはオプションです。
このパラメータは、エラー・メッセージ出力ファイルの名前を指定します。情報メッセージおよびエラー・メッセージは、ERRTYPE
パラメータを指定したかどうかに関係なく、標準出力に送信されます。基本的に、ERRTYPE
ファイルは、エラー・メッセージが追加されたINTYPE
ファイルのコピーです。ほとんどの場合、エラー・メッセージにはエラーの原因となったテキストへのポインタが含まれます。
コマンドラインで、拡張子を付けずにファイル名をERRTYPE
パラメータに指定すると、.TLS
や.tls
などのプラットフォーム固有の拡張子が自動的に追加されます。
このパラメータは、OTTユーティリティで生成するヘッダー・ファイル(.h
)の名前を指定します。コマンド・ラインで指定されたHFILE
には、INTYPE
ファイルに記述した型の宣言でヘッダー・ファイルを指定しなかったものが含まれます。
INTYPE
ファイルで各型のヘッダー・ファイルを個々に指定していない場合は、このパラメータが必要です。また、INTYPE
ファイルに記述していない型を、2つ以上の異なるファイルで宣言されている他の型で使用する場合は、INTYPEファイルに記述していない型も生成する必要があります。そのような場合もこのパラメータが必要です。
コマンドラインまたはINTYPE
ファイルで、拡張子を付けずにファイル名をHFILE
パラメータに指定すると、.H
や.h
などのプラットフォーム固有の拡張子が自動的に追加されます。
このパラメータは、オブジェクト型指定のリストを読み取る元のファイル名を指定します。OTTユーティリティによって、リストにある各型が変換されます。INTYPE
パラメータが指定されていない場合は、ユーザーのスキーマにある型すべてが変換されます。
コマンドラインで、拡張子を付けずにファイル名をINTYPE
パラメータに指定すると、.TYP
や.typ
などのプラットフォーム固有の拡張子が自動的に追加されます。
USERID
が第1パラメータ、INTYPE
が第2パラメータで、USERID=
を省略した場合は、INTYPE=
も省略できます。
INTYPE
ファイルは、型宣言に対するMakeファイルとみなすことができます。このファイルには、C++クラスを必要とする型がリストされます。
このパラメータは、OTTユーティリティで生成するマッピング・ファイル(XXX
.cpp
)とそれに対応するヘッダー・ファイル(XXX
.h
)の名前を指定します。XXX
.cpp
ファイルにはマッピングを登録する関数の実装が格納され、XXX
.h
ファイルにはその関数のプロトタイプが格納されます。
このパラメータは、コマンドラインまたはINTYPE
ファイルに指定できます。
このパラメータは、OTTユーティリティで生成する、マッピングの登録に使用する関数の名前を指定します。
このパラメータを省略すると、マッピングを登録する関数の名前は、MAPFILE
パラメータに指定されているファイル名に基づいて作成されます。
このパラメータは、コマンドラインまたはINTYPE
ファイルに指定できます。
このパラメータは、OTTユーティリティが処理を行うすべてのオブジェクト・データ型に対して型情報を書き込むファイルの名前を指定します。このファイルには、INTYPE
ファイルで明示的に指定したすべての型が含まれます。さらに、変換対象である他の型の宣言で使用しているために変換された型が含まれる場合もあります。このファイルは、それ以後にOTTユーティリティを起動するときにINTYPE
ファイルとして使用できます。
INTYPE
パラメータとOUTTYPE
パラメータが同一のファイルを参照している場合、INTYPE
ファイルの古い情報は、新しいINTYPE
の情報によって置換されます。これは、型の変更から始まり、型宣言の生成、ソースコードの編集、プリコンパイル、コンパイル、デバッグに至るサイクル内で、同一のINTYPE
ファイルを繰返し使用するときに便利です。
コマンドラインまたはINTYPE
ファイルに、拡張子を付けずにファイル名をOUTTYPE
パラメータに指定すると、.TYP
や.typ
などのプラットフォーム固有の拡張子が自動的に追加されます。
OUTTYPEファイルで命名されたデフォルト・スキーマに基づく型のデータベース名を修飾する場合、このパラメータで制御します。OTTユーティリティによって生成されたOUTTYPEファイルには、型名を含めて、OTTユーティリティで処理された型の情報が記述されます。次の値が有効です。
ALWAYS
(デフォルト)の場合、OUTTYPEファイル内のすべての型名はスキーマ名で修飾されます。
IF_NEEDED
の場合、デフォルト・スキーマに所属するOUTTYPEファイル内の型名は、スキーマ名で修飾されません。その他のスキーマに所属する型名は、スキーマ名で修飾されます。
FROM_INTYPE
の場合、INTYPEファイルに記述されている型は、INTYPEファイル内のスキーマ名で修飾されている場合に限って、OUTTYPEファイル内のスキーマ名で修飾されます。INTYPEファイルには記述されていないが、型の依存性のために生成されたデフォルト・スキーマ内の型は、その型に依存しているOTTユーティリティで最初に検出された型がスキーマ名付きで記述されている場合にのみ、スキーマ名付きで記述されます。ただし、OTTユーティリティが接続しているデフォルト・スキーマにない型は、常に、明示的に指定したスキーマ名付きで記述されます。
デフォルト・スキーマ以外のスキーマに基づく型の名前は、OUTTYPEファイル内のスキーマ名で常に修飾されます。
スキーマ名の有無によって、プログラム実行中に型を検索するスキーマが決定されます。
例8-4 OTTユーティリティでのSCHEMA_NAMESパラメータの使用方法
SCHEMA_NAMES
パラメータがFROM_INTYPE
に設定され、INTYPE
ファイルに次の指定がある例を想定します。
TYPE Person TYPE joe.Dept TYPE sam.Company
OTTユーティリティとアプリケーションの両方がスキーマjoeに接続する場合、アプリケーションはOTTユーティリティが使用する型と同じ型(joe.Person
)を使用します。OTTユーティリティはスキーマjoe
に接続しているが、アプリケーションはスキーマmary
に接続している場合、アプリケーションはmary.Person
型を使用します。この動作は、スキーマjoe
とスキーマmary
で同一のCREATE TYPE Person
文が実行されている場合にのみ適切です。
一方、アプリケーションは、接続しているスキーマに関係なく、joe.Dept
型を使用します。この動作のためには、スキーマ名をINTYPE
ファイルで使用している型名に挿入する必要があります。
ユーザーが明示的に名前を指定していない型が、OTTユーティリティによって変換される場合があります。たとえば、次のSQL宣言を想定します。
CREATE TYPE Address AS OBJECT ( street VARCHAR2(40), city VARCHAR(30), state CHAR(2), zip_code CHAR(10) ); CREATE TYPE Person AS OBJECT ( name CHAR(20), age NUMBER, addr ADDRESS );
OTTユーティリティはスキーマjoe
に接続し、SCHEMA_NAMES=FROM_INTYPE
が指定され、ユーザーのINTYPE
ファイルには、TYPE Person
またはTYPE joe.Person
のいずれかが含まれていると仮定します。INTYPE
ファイルには、joe.Person
型でネストしたオブジェクト型として使用されているjoe.Address
型は指定されていません。
INTYPE
ファイルにType Person
が指定されている場合は、TYPE Person
とTYPE Address
がOUTTYPE
ファイルに指定されます。
INTYPE
ファイルにTYPE joe.Person
が指定されている場合は、TYPE joe.Person
とTYPE joe.Address
がOUTTYPE
ファイルに指定されます。
OTTユーティリティが変換する複数の型には、joe.Address
型が埋め込まれているが、そのことがINTYPE
ファイルには明示的に記述されていない場合、スキーマ名を使用するかどうかの判断は、埋め込まれたjoe.Address
型をOTTユーティリティが最初に検出したときに行われます。なんらかの理由で、ユーザーがスキーマ名をjoe.Address
型には付け、Person
型には付けないようにするには、TYPE joe.Address
のように、この内容をINTYPE
ファイルで明示的に指定する必要があります。
各型を単一のスキーマ内で宣言する通常の場合は、すべての型名をINTYPE
ファイル内のスキーマ名で修飾することが最も安全です。
このパラメータは、INTYPE
ファイルに明示的にリストされていない型の依存性を変換するかどうかを指定します。次の値が有効です。
TRUE
(デフォルト): 他の型に必要な型で、INTYPE
ファイルに指定されていない型が生成されます。
FALSE
: INTYPE
ファイルに指定されていない型は生成されません。これは、ファイルに指定されていない型が、生成された他の型に対する属性の型として使用されている場合にも適用されます。
このパラメータは、アプリケーションでUnicode (UTF16
)をサポートするかどうかを指定します。
NONE
(デフォルト)
ALL
: すべてのCHAR
(CHAR
/VARCHAR
)およびNCHAR
(NCHAR
/NVARCHAR2
)型属性が、OTT生成のC++クラス・ファイルでUString
型として宣言されます。対応するget
XXX
()
/set
XXX
()
の戻り値または戻りパラメータは、UString
型です。また、生成される永続演算子newは、UString
引数のみ受け入れます。
この設定は、クライアント・キャラクタセットおよび各国語キャラクタセットの両方がUTF16
である場合に必要です。
ONLYNCHAR
: ALL
オプションに類似していますが、NCHAR
型属性のみがUString
として宣言されます。
この設定は、アプリケーションにおいて環境の各国語キャラクタセットのみをUTF16
に設定する場合に必要です。
例8-5 OTTでUnicodeをサポートするためのスキーマの定義方法
create type CitiesList as varray(100) of varchar2(100); create type Country as object ( CNo Number(10), CName Varchar2(100), CNationalName NVarchar2(100), MainCities CitiesList);
例8-6 OTTでのUNICODE=ALLパラメータの使用方法
class Country : public oracle::occi::PObject { private: oracle::occi::Number CNO; oracle::occi::UString CNAME; oracle::occi::UString CNATIONALNAME; OCCI_STD_NAMESPACE:::vector< oracle::occi::UString > MAINCITIES; public: oracle::occi::Number getCno() const; void setCno(const oracle::occi::Number &value); oracle::occi::UString getCname() const; void setCname(const oracle::occi::UString &value); oracle::occi::UString getCnationalname() const; void setCnationalname(const oracle::occi::UString &value); OCCI_STD_NAMESPACE::vector< oracle::occi::UString >& getMaincities(); const OCCI_STD_NAMESPACE::vector< oracle::occi::UString >& getMaincities() const; void setMaincities(const OCCI_STD_NAMESPACE::vector< oracle::occi::UString > &value); ... }
例8-7 OTTでのUNICODE=ONLYCHARパラメータの使用方法
class Country : public oracle::occi::PObject { private: oracle::occi::Number CNO; oracle::occi::string CNAME; oracle::occi::UString CNATIONALNAME; OCCI_STD_NAMESPACE::vector< std::string > MAINCITIES; public: oracle::occi::Number getCno() const; void setCno(const oracle::occi::Number &value); oracle::occi::string getCname() const; void setCname(const OCCI_STD_NAMESPACE::string &value); oracle::occi::UString getCnationalname() const; void setCnationalname(const oracle::occi::UString &value); OCCI_STD_NAMESPACE::vector< OCCI_STD_NAMESPACE::string>& getMaincities(); const OCCI_STD_NAMESPACE::vector< OCCI_STD_NAMESPACE::string >& getMaincities() const; void setMaincities(const OCCI_STD_NAMESPACE::vector < OCCI_STD_NAMESPACE::string > &value); ... }
このパラメータは、ユーザーが追加したコードを引き継ぐために、OTTマーカーをサポートするかどうかを指定します。次の値が有効です。
FALSE
(デフォルト): OTT_USERCODE_START
とOTT_USERCODE_END
の2つのマーカーの間にユーザーがコードを指定しても、追加したコードは引き継がれません。
TRUE
: OTT_USER_CODESTART
とOTT_USERCODE_END
の2つのマーカーの間にユーザーが指定したコードは、同じファイルが再生成されたときに引き継がれます。
このパラメータは、Oracleユーザー名およびオプションのデータベース名(Oracle Netのデータベース指定文字列)を指定します。データベース名を省略すると、デフォルトのデータベースが使用されます。
USERID=username[@db_name]
これが第1パラメータである場合は、USERID=
を省略して、次のように指定できます。
OTT username ...
ユーザーIDに対応するパスワードが要求されるので注意してください。
このパラメータはオプションです。このパラメータを省略すると、OTTユーティリティは、ユーザーOPS$username
でデフォルトのデータベースに自動的に接続します。username
は、オペレーティング・システムのユーザー名です。
OTTパラメータは、コマンドラインまたはコマンドラインで名前が指定されたCONFIG
ファイル、あるいはその両方に指定できます。パラメータの一部は、INTYPE
ファイルにも指定できます。
OTTユーティリティは、次のように起動します。
OTT parameters
CONFIG
パラメータを使用して、構成ファイルの名前をコマンドラインで次のように指定できます。
CONFIG=filename
コマンドラインでこのパラメータの名前を指定すると、他のパラメータは、ファイル名filename
の構成ファイルから読み取られます。
パラメータは、オペレーティング・システム固有の位置にあるデフォルトの構成ファイルからも読み取られます。このファイルの存在は必要ですが、空でも構いません。構成ファイルにデータを入力する場合、空白は使用できないこと、パラメータは1行ごとに入力する必要があることに注意してください。
引数を指定しないでOTTユーティリティを実行すると、オンライン・パラメータ・リファレンスが表示されます。
OTTユーティリティによって変換される型は、INTYPE
パラメータで指定されたファイルに従って名前が付けられます。CASE
、CPPFILE
、HFILE
、INITFILE
、INITFUNC
、MAPFILE
およびMAPFNC
の各パラメータは、INTYPE
ファイルにも指定できます。OTTユーティリティによって生成されたOUTTYPE
ファイルにはCASE
パラメータが含まれ、初期化ファイルが生成された場合はINITFILE
パラメータとINITFUNC
パラメータが、C++コードが生成された場合はMAPFILE
パラメータとMAPFUNC
パラメータが含まれます。OUTTYPE
ファイルおよびC++用のCPPFILE
は、各型に対するHFILE
を個別に指定します。
OTTコマンドの大/小文字区別は、オペレーティング・システムによって異なります。
現在、OTTユーティリティでは、コマンドラインまたはINTYPE
ファイルにユーザーが指定したファイル名を比較することによって、2つのファイルが同一かどうかを判断しています。ただし、OTTユーティリティで2つのファイル名が同一のファイルを参照しているかどうかを判別する必要がある場合、1つの潜在的な問題が生じます。たとえば、OTTで生成されたファイルfoo1.hで、foo1.h
に記述されている型宣言と、/private/smith/foo1.h
に記述されている別の型宣言が必要な場合、OTTユーティリティは、2つのファイルが同一の場合は1つの#include
を、異なる場合は2つの#include
を生成する必要があります。しかし、実際には2つのファイルが異なるとみなし、次のように2つの#include
を生成します。
#ifndef FOO1_ORACLE #include "foo1.h" #endif #ifndef FOO1_ORACLE #include "/private/smith/foo1.h" #endif
foo1.h
と/private/smith/foo1.h
が異なるファイルである場合は、最初のファイルのみがインクルードされることになります。foo1.h
と/private/smith/foo1.h
が同一ファイルである場合は、冗長な#include
が記述されることになります。
そのため、1つのファイルをコマンドラインまたはINTYPE
ファイルに複数回指定する場合は、ファイルの各指定で同じファイル名を使用する必要があります。
現行リリースにおけるMicrosoft WindowsでのOTT実行可能ファイルは、前回のリリースのott.exe
ではなく、ott.bat
です。ottの実行後、スクリプトがすぐに終了するため、これによってWindowsのバッチ・スクリプトが破棄される可能性があります。この問題を修正するには、Windowsバッチ・スクリプトで、次のようにOTTを起動する必要があります。
call ott [arguments]
注意: 中間的な解決策として、スクリプトが修正されるまで、ORACLE_HOME\precomp\admin\ott.exe を使用できます。ただし、この中間的な解決策は将来のリリースでは提供されません。 |
OTTユーティリティの実行時に、INTYPE
ファイルは、変換するデータベース型をOTTユーティリティに指定します。INTYPE
ファイルは、生成する構造体やクラスの名前付けも制御します。INTYPE
ファイルは、直接作成できますが、以前にOTTユーティリティを起動したときに生成されたOUTTYPE
ファイルを利用することもできます。INTYPE
ファイルを使用しないと、OTTユーティリティが接続しているスキーマのすべての型が変換されます。
例8-8 OTTユーティリティを使用したユーザー定義INTYPEファイルの作成方法
CASE=LOWER TYPE employee TRANSLATE SALARY$ AS salary DEPTNO AS department TYPE ADDRESS TYPE item TYPE "Person" TYPE PURCHASE_ORDER AS p_o
1行目のCASE
パラメータは、小文字によるC識別子の生成を示しています。ただし、このCASE
パラメータは、INTYPE
ファイルに明示的に記述されていない識別子にのみ適用されます。そのため、常にemployee
はemployee
、ADDRESS
はADDRESS
というC構造体になります。これらの構造体のメンバーには、小文字で名前が指定されます。
TYPE
キーワードで始まる行は、変換するデータベース内の型を指定します。この例では、EMPLOYEE
型、ADDRESS
型、ITEM
型、PERSON
型およびPURCHASE_ORDER
型を変換するように設定しています。
TRANSLATE...AS
キーワードは、オブジェクト型をC構造体に変換するときに、オブジェクト属性の名前を変更することを指定しています。この例では、employee
型のSALARY$
属性がsalary
に変換されます。
最終行のAS
キーワードは、オブジェクト型を構造体に変換するときに、名前を変更することを指定しています。この例では、purchase_order
データベース型をp_o
と呼ばれる構造体に変換します。
OTTユーティリティでは、INTYPE
ファイルにリストされていない他の型の変換が必要になる場合があります。これは、OTTユーティリティは、変換前にINTYPE
ファイルにある型の依存性を分析し、必要に応じて他の型を変換するためです。たとえば、ADDRESS
型はINTYPE
ファイルにリストされていなくても、Person
型にADDRESS
型の属性がある場合、OTTユーティリティでは、Person
型の定義が必須のため、ADDRESS
を変換します。
INTYPE
ファイルに指定されていない必要なオブジェクト型を、OTTユーティリティで生成するかどうかを指定できます。必要なオブジェクト型をOTTユーティリティで生成しない場合は、TRANSITIVE=FALSE
を設定してください。デフォルトは、TRANSITIVE=TRUE
です。
INTYPE
ファイルでは、通常の大/小文字の区別がないSQL識別子は、大/小文字のどのような組合せのつづりでも可能です。引用符は付けません。
CREATE TYPE "Person"
などの大/小文字を区別して作成されているSQL識別子を参照するには、TYPE "Person"
のように引用符を使用してください。SQL識別子は、宣言時に引用符が付けられた場合、大/小文字が区別されます。引用符は、TYPE "CASE"
などのOTT予約語であるSQL識別子を参照するためにも使用できます。この場合、そのSQL識別子が、CREATE TYPE Case
のように大/小文字の区別なしに作成されていた場合、引用符付きの名前は大文字であることが必要です。SQL識別子の名前を参照するためのOTT予約語に引用符が付けられていない場合、OTTユーティリティは、INTYPE
ファイルに構文エラーをレポートします。
INTYPE
およびOUTTYPE
ファイルでは、OTTにより変換される型がリストされ、型または属性名の有効なC言語もしくはC++言語の識別子への変換方法を決定するときに必要なすべての情報が提供されます。これらのファイルには1つ以上の型指定が含まれており、CASE
、CPPFILE
、HFILE
、INITFILE
、INITFUNC
、MAPFILE
またはMAPFUNC
の指定が含まれている場合もあります。
CASE
、INITFILE
、INITFUNC
、MAPFILE
またはMAPFUNC
オプションを指定する場合は、すべての型指定に先行して指定する必要があります。これらのオプションがコマンドラインとINTYPE
ファイルの両方に指定されている場合は、コマンドラインの値が使用されます。
関連項目: 簡単なユーザー定義のINTYPE ファイルの例およびこのファイルからOTTユーティリティによって生成される完全なOUTTYPE ファイルの例は、「OUTTYPEファイルの概要」を参照してください |
INTYPE
ファイル内の型指定によって、変換するオブジェクト・データ型の名前が指定されます。次の記述は、ユーザー作成INTYPE
ファイルの例です。
TYPE employee TRANSLATE SALARY$ AS salary DEPTNO AS department TYPE ADDRESS TYPE PURCHASE_ORDER AS p_o
型指定の構造は、次のとおりです。
TYPE type_name [GENERATE type_identifier] [AS type_identifier] [VERSION [=] version_string] [HFILE [=] hfile_name] [CPPFILE [=] cppfile_name] [TRANSLATE{member_name [AS identifier]}...]
type_name
の構文は、次のフォーマットに従います。
[schema_name.]type_name
この構文では、schema_name
は、指定されたオブジェクト・データ型を所有するスキーマの名前で、type_name
はその型の名前です。指定されない場合のデフォルトのスキーマは、OTTユーティリティを起動したuserIDのスキーマです。特定のスキーマを使用するには、schema_nameを使用する必要があります。
型指定の構成要素は、次のとおりです。
type_name
: オブジェクト・データ型の名前です。
type_identifier
: クラスの表現に使用するCまたはC++の識別子です。GENERATE
句は、OTTユーティリティが生成するクラスの名前を指定するために使用されます。記述するクラスの名前は、AS句によって指定されます。GENERATE
句は、通常、クラスを拡張するために使用されます。ユーザー定義型を示すC構造体またはC++クラスの名前は、必要に応じて、GENERATE
句を伴わずに、AS
句によって指定されます。
version_string
: OTTユーティリティの以前の起動によってコードが生成されたときに使用された型のバージョン文字列です。バージョン文字列はOTTユーティリティによって生成されてOUTTYPE
ファイルに書き込まれます。このファイルは、後のOTTユーティリティの起動時にINTYPE
ファイルとして使用できます。バージョン文字列はOTTユーティリティの動作には影響しませんが、実行中のプログラムで使用されるオブジェクト・データ型のバージョンの選択に使用できます。
hfile_name
: 対応するクラスの宣言が書き込まれるヘッダー・ファイルの名前です。HFILE
句を省略すると、コマンドラインのHFILE
パラメータで指定したファイルが使用されます。
cppfile_name
: 対応するクラスのメソッド実装が書き込まれるC++ソース・ファイルの名前です。CPPFILE
句を省略すると、コマンドラインのCPPFILE
パラメータで指定したファイルが使用されます。
member_name
: 識別子に変換される属性(データ・メンバー)の名前です。
identifier
: プログラムで属性を表現するために使用するCまたはC++の識別子です。この方法によって、任意の数の属性に対して識別子を指定できます。属性が指定されていない場合には、デフォルトの名前マッピング・アルゴリズムが使用されます。
オブジェクト・データ型は、次のいずれかの場合に変換できます。
INTYPE
ファイルに指定されている場合。
そのオブジェクト・データ型には変換が必要な別の型の宣言が必要で、TRANSITIVE
パラメータがTRUE
に設定されている場合。
明示的に記述されていない型が、あるファイル内で正確に宣言された型に必要とされる場合、必要とされる型の変換結果は、その結果を必要とする明示的に宣言された型と同じファイルに書き込まれます。
明示的に記述されていない型が、複数の異なるファイル内で宣言された型に必要とされる場合、必要とされる型の変換結果は、グローバルなHFILE
ファイルに書き込まれます。
INTYPE
ファイルに指定されていない必要なオブジェクト型を、OTTユーティリティで生成するかどうかを指定できます。必要なオブジェクト型をOTTユーティリティで生成しない場合は、TRANSITIVE=FALSE
を設定してください。デフォルトは、TRANSITIVE=TRUE
です。
OTTユーティリティで生成したHFILE
ファイルには、他の必要なファイルをインクルード(#include
)し、ファイル名から作成した記号を定義(#define
)します。この記号#define
は、関連するHFILE
ファイルがインクルードされているかどうかの判断に使用できます。たとえば、次の型を持つデータベースについて考えます。
create type px1 AS OBJECT (col1 number, col2 integer); create type px2 AS OBJECT (col1 px1); create type px3 AS OBJECT (col1 px1);
INTYPE
ファイルには、次の情報が記述されます。
CASE=lower type pxl hfile tott95a.h type px3 hfile tott95b.h
次のように、OTTユーティリティを起動します。
>ott hr intype=tott95i.typ outtype=tott95o.typ code=cpp
...
Enter password: password
OTTユーティリティは、tott95a.h
とtott95b.h
というファイル名を持つ2つのヘッダー・ファイルを作成します。これらのファイルを次に示します。
例8-9 ott95a.hのリスト
#ifndef TOTT95A_ORACLE # define TOTT95A_ORACLE #ifndef OCCI_ORACLE # include <occi.h> #endif /************************************************************/ // generated declarations for the PX1 object type. /************************************************************/ class px1 : public oracle::occi::PObject { protected: oracle::occi::Number col1; oracle::occi::Number col2; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void *operator new(size_t, void *ctxOCCI_); void *operator new(size_t size, const oracle::occi::Connection *sess, const OCCI_STD_NAMESPACE::string &tableName, const OCCI_STD_NAMESPACE::string &typeName, const OCCI_STD_NAMESPACE::string &tableSchema, const OCCI_STD_NAMESPACE::string &typeSchema); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; px1(); px1(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); ~px1(); }; #endif
例8-10 ott95b.hのリスト
#ifndef TOTT95B_ORACLE # define TOTT95B_ORACLE #ifndef OCCI_ORACLE # include <occi.h> #endif #ifndef TOTT95A_ORACLE # include "tott95a.h" #endif /************************************************************/ // generated declarations for the PX3 object type. /************************************************************/ class px3 : public oracle::occi::PObject { protected: px1 * col1; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void *operator new(size_t, void *ctxOCCI_); void *operator new(size_t size, const oracle::occi::Connection *sess, const OCCI_STD_NAMESPACE::string &tableName, const OCCI_STD_NAMESPACE::string &typeName, const OCCI_STD_NAMESPACE::string &tableSchema, const OCCI_STD_NAMESPACE::string &typeSchema); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; px3(); px3(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); ~px3(); }; #endif
tott95b.h
ファイルでは、記号TOTT95B_ORACLE
がファイルの先頭に定義(#define
)されています。これによって、次の構造体を使用してこのヘッダー・ファイルを別のファイルに条件付きでインクルード(#include
)できます。
#ifndef TOTT95B_ORACLE #include "tott95b.h" #endif
この方法を使用すると、たとえば、foo.h
にtott95b.h
をインクルード(#include
)できます。この場合、foo.h
に他のファイルのインクルード(#include
)があるかどうか、また、tott95b.h
のインクルード(#include
)があるかどうかを事前に知る必要はありません。
次に、ファイルtott95a.h
がインクルードされるのは、tott95a.h
に必要なstruct px1
の宣言が含まれているためです。INTYPE
ファイルにより型宣言の複数ファイルへの書込みが要求される場合は、OTTユーティリティにより、その他の各HFILE
に#include
する必要があるファイルが決定され、必要な#include
が生成されます。
OTTユーティリティでは、この#include
に" "が使用されます。tott95b.h
がインクルードされているプログラムをコンパイルするとき、tott95a.h
の検索は、ソース・プログラムが検出された場所から開始され、以降は実装定義の検索規則に従います。この方法でtott95a.h
を検索できない場合は、tott95a.h
の位置を指定するために完全なファイル名(スラッシュ文字(/
)で始まるUNIXの絶対パス名など)がINTYPE
ファイルに必要です。
OTTユーティリティによって、データベース型からC++クラスが生成されると、構造体またはクラスには、オブジェクト型の各属性に対応する1つの要素が含まれます。属性のデータ型は、Oracleオブジェクト・データ型で使用される型にマッピングされます。Oracleのデータ型には、事前定義の基本的な一連の型が組み込まれており、オブジェクト型やコレクションなどのユーザー定義の型の作成をサポートします。
一連の事前定義の型には、数値型や文字型を含む、プログラマによく知られている標準の型があります。それには、ラージ・オブジェクト・データ型(BLOB
またはCLOB
など)も含まれます。
例8-11 OTTユーティリティを使用したオブジェクト属性の表現方法
Oracleには、オブジェクト型属性をC++クラスで表現するための一連の事前定義の型も含まれています。次のようなオブジェクト型定義とそれに対応するOTT生成の構造体宣言を想定します。
CREATE TYPE employee AS OBJECT ( name VARCHAR2(30), empno NUMBER, deptno NUMBER, hiredate DATE, salary NUMBER );
CASE
パラメータがLOWER
に設定され、型名または属性名の明示的なマッピングがないと仮定すると、OTTユーティリティの出力は、次のようになります。
#ifndef DATATYPES_ORACLE # define DATATYPES_ORACLE #ifndef OCCI_ORACLE # include <occi.h> #endif /************************************************************/ // generated declarations for the EMPLOYEE object type. /************************************************************/ class employee : public oracle::occi::PObject { protected: OCCI_STD_NAMESPACE::string NAME; oracle::occi::Number EMPNO; oracle::occi::Number DEPTNO; oracle::occi::Date HIREDATE; oracle::occi::Number SALARY; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void *operator new(size_t, void *ctxOCCI_); void *operator new(size_t size, const oracle::occi::Connection *sess, const OCCI_STD_NAMESPACE::string &tableName, const OCCI_STD_NAMESPACE::string &typeName, const OCCI_STD_NAMESPACE::string &tableSchema, const OCCI_STD_NAMESPACE::string &typeSchema); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; employee(); employee(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); ~employee(); }; #endif
表8-2は、属性として使用できる型から、OTTユーティリティで生成されるオブジェクト・データ型へのマッピングのリストです。
表8-2 オブジェクト型属性のC++オブジェクト・データ型マッピング
オブジェクト属性の型 | C++マッピング |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ネストされたオブジェクト型のC++の名前 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例8-12 OTTユーティリティを使用したオブジェクト・データ型のマップ方法
この例では、次のデータベース型が作成されていることを想定しています。
CREATE TYPE my_varray AS VARRAY(5) of integer; CREATE TYPE object_type AS OBJECT (object_name VARCHAR2(20)); CREATE TYPE other_type AS OBJECT (object_number NUMBER); CREATE TYPE my_table AS TABLE OF object_type; CREATE TYPE many_types AS OBJECT ( the_varchar VARCHAR2(30), the_char CHAR(3), the_blob BLOB, the_clob CLOB, the_object object_type, another_ref REF other_type, the_ref REF many_types, the_varray my_varray, the_table my_table, the_date DATE, the_num NUMBER, the_raw RAW(255) );
INTYPE
ファイルが存在し、次のオプションが含まれます。
CASE = LOWER TYPE many_types
次の記述は、C++に関するOTTの型マッピングの例です。前項の例で作成された型と次のオプションを含むINTYPE
ファイルを前提にしています。
CASE = LOWER TYPE many_types
#ifndef MYFILENAME_ORACLE #define MYFILENAME_ORACLE #ifndef OCCI_ORACLE #include <occi.h> #endif /************************************************************/ // generated declarations for the OBJECT_TYPE object type. /************************************************************/ class object_type : public oracle::occi::PObject { protected: OCCI_STD_NAMESPACE::string object_name; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; object_type(); object_type(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); }; /************************************************************/ // generated declarations for the OTHER_TYPE object type. /************************************************************/ class other_type : public oracle::occi::PObject { protected: oracle::occi::Number object_number; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; other_type(); other_type(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); }; /************************************************************/ // generated declarations for the MANY_TYPES object type. /************************************************************/ class many_types : public oracle::occi::PObject { protected: OCCI_STD_NAMESPACE::string the_varchar; OCCI_STD_NAMESPACE::string the_char; oracle::occi::Blob the_blob; oracle::occi::Clob the_clob; object_type * the_object; oracle::occi::Ref< other_type > another_ref; oracle::occi::Ref< many_types > the_ref; OCCI_STD_NAMESPACE::vector< oracle::occi::Number > the_varray; OCCI_STD_NAMESPACE::vector< object_type * > the_table; oracle::occi::Date the_date; oracle::occi::Number the_num; oracle::occi::Bytes the_raw; public: void *operator new(size_t size); void *operator new(size_t size, const oracle::occi::Connection * sess, const OCCI_STD_NAMESPACE::string& table); void getSQLTypeName(oracle::occi::Environment *env, void **schemaName, unsigned int &schemaNameLen, void **typeName, unsigned int &typeNameLen) const; many_types(); many_types(void *ctxOCCI_) : oracle::occi::PObject (ctxOCCI_) { }; static void *readSQL(void *ctxOCCI_); virtual void readSQL(oracle::occi::AnyData& streamOCCI_); static void writeSQL(void *objOCCI_, void *ctxOCCI_); virtual void writeSQL(oracle::occi::AnyData& streamOCCI_); }; #endif
OTTユーティリティでは、次のC++クラス宣言が生成されます(コメントはOTT出力の一部ではなく、例を明解にする目的でのみ追加したものです)。
C++では、TRANSITIVE=TRUE
の場合、OTTユーティリティは、ポインタまたはオブジェクト型属性のREF
によってのみアクセスされる型を含む、変換対象の型の属性に使用されている型をすべて自動的に変換します。C++の例ではmany_types
オブジェクトのみがINTYPE
ファイルで指定されていましたが、many_types
オブジェクトのREF
によってのみアクセスされるother_type
オブジェクトを含めて、すべてのオブジェクト型に対してクラス宣言が生成されます。
オブジェクト型または属性に対するCまたはC++の識別子名を作成する場合、OTTユーティリティは、その名前をデータベース・キャラクタ・セットから有効なCまたはC++の識別子に変換します。最初に、データベース・キャラクタ・セットからOTTユーティリティで使用するキャラクタ・セットに、名前が変換されます。次に、変換した結果の名前がINTYPE
ファイルに指定されている場合は、その変換内容が使用されます。それ以外の場合、OTTユーティリティは、CASEパラメータに指定されている大/小文字を適用して、名前を文字ごとにコンパイラのキャラクタ・セットに変換します。詳細を次に説明します。
OTTユーティリティによってデータベース・エンティティ名が読み取られると、データベース・キャラクタ・セットからOTTユーティリティで使用するキャラクタ・セットに自動的に変換されます。OTTユーティリティがデータベース・エンティティ名を正常に読み取るには、その名前のすべての文字がOTTのキャラクタ・セット内で検出される必要はあります。ただし、文字によっては2つのキャラクタ・セット間でエンコーディングが異なる場合があります。
必要な文字がOTTユーティリティで使用するキャラクタ・セットにすべて含まれていることを保証するには、データベース・キャラクタ・セットと同じものを使用するのが最も簡単な方法です。ただし、OTTのキャラクタ・セットは、コンパイラのキャラクタ・セットのスーパーセットである必要があります。つまり、コンパイラのキャラクタ・セットが7ビットASCIIの場合、OTTのキャラクタ・セットはサブセットとして7ビットASCIIを含む必要があります。コンパイラのキャラクタ・セットが7ビットEBCDICの場合は、OTTのキャラクタ・セットはサブセットとして7ビットEBCDICを含む必要があります。ユーザーは、NLS_LANG
環境変数を設定するか、それ以外のオペレーティング・システム固有のメカニズムを利用して、OTTユーティリティが使用するキャラクタ・セットを指定します。
OTTユーティリティは、読み取ったデータベース・エンティティの名前を、OTTユーティリティで使用するキャラクタ・セットからコンパイラのキャラクタ・セットに変換します。名前の変換内容がINTYPE
ファイルに指定されている場合、OTTユーティリティはその変換内容を使用します。
それ以外の場合、OTTユーティリティは、次のように名前を変換します。
OTTのキャラクタ・セットがマルチバイト・キャラクタ・セットの場合、名前の中で等価のシングルバイト文字を持つすべてのマルチバイト文字は、該当するシングルバイト文字に変換されます。
名前は、OTTのキャラクタ・セットからコンパイラのキャラクタ・セットに変換されます。コンパイラのキャラクタ・セットは、US7ASCII
などのシングルバイト・キャラクタ・セットです。
CASE
パラメータの定義に従って、文字の大/小文字が設定されます。そして、C言語もしくはC++言語の識別子で無効な文字、またはコンパイラのキャラクタ・セットに変換内容がない文字は、アンダースコア文字(_
)に置き換えられます。1文字でもアンダースコアに置き換えられると、OTTユーティリティから警告メッセージが表示されます。名前に含まれる文字がすべてアンダースコアに置き換えられると、OTTユーティリティからエラー・メッセージが表示されます。
文字単位の名前の変換では、コンパイラのキャラクタ・セットにあるアンダースコア、数字またはシングルバイト文字は変更されません。したがって、有効なCまたはC++の識別子は変更されません。
名前の変換ではたとえば、ウムラウトの付いたo、アクセント符号の付いたaなどのシングルバイト文字をアクセントなしのoやaに変換したり、またマルチバイト文字をシングルバイトと等価に変換できます。名前に等価のシングルバイトがないマルチバイト文字がある場合、通常、その名前の変換はエラーとなります。この場合、ユーザーは、INTYPE
ファイルで名前の変換を指定する必要があります。
C言語の同一の名前に複数のデータベース識別子がマッピングされている場合に生じる名前の競合は、OTTユーティリティでは検出されません。また、データベース識別子がCキーワードにマッピングされるときの名前の問題も検出されません。
OUTTYPE
ファイルは、OTTコマンドラインで名前が指定されます。OTTユーティリティによって、C++ヘッダー・ファイルが生成されると、変換の結果がOUTTYPE
ファイルに出力されます。このファイルには、変換された各型のエントリが、そのバージョン文字列も含めて格納され、さらに、C++表現で記述されたヘッダー・ファイルが格納されます。
あるOTTユーティリティの実行によるOUTTYPE
ファイルは、そのOTTユーティリティのその後の起動でINTYPE
ファイルとして使用できます。
例8-13 OTTユーティリティによって生成されるOUTTYPEファイル
このINTYPE
ファイルでは、プログラマによって、OTT生成のC++識別子に対して大/小文字の区別が指定され、変換する型のリストが用意されています。これらの型のうちの2つについては、ネーミング規則が指定されています。OTTユーティリティ実行後のOUTTYPE
ファイルは、次のようになります。
次に例を示します。
CASE = LOWER TYPE EMPLOYEE AS employee VERSION = "$8.0" HFILE = demo.h TRANSLATE SALARY$ AS salary DEPTNO AS department TYPE ADDRESS AS ADDRESS VERSION = "$8.0" HFILE = demo.h TYPE ITEM AS item VERSION = "$8.0" HFILE = demo.h TYPE "Person" AS Person VERSION = "$8.0" HFILE = demo.h TYPE PURCHASE_ORDER AS p_o VERSION = "$8.0" HFILE = demo.h
INTYPE
ファイルで指定しなかった型がOUTTYPE
ファイルに含まれている場合があります。たとえば、INTYPE
ファイルにperson
型のみの変換を指定した場合を想定します。
CASE = LOWER TYPE PERSON
person
型の定義にaddress
型の属性が含まれている場合、OUTTYPE
ファイルには、PERSON
とADDRESS
の両方のエントリが含まれます。person
型を完全に変換するには、最初にaddress
を変換する必要があります。
OTTユーティリティは、変換前にINTYPE
ファイルにある型の依存性を分析し、必要に応じて他の型を変換します。
INTYPE
ファイルに指定されていない必要なオブジェクト型を、OTTユーティリティで生成するかどうかを指定できます。必要なオブジェクト型をOTTユーティリティで生成しない場合は、TRANSITIVE=FALSE
を設定してください。デフォルトは、TRANSITIVE=TRUE
です。
OTTユーティリティは、オブジェクトを生成し、SQLデータ型をC++クラスにマッピングします。OTTユーティリティは、オブジェクトをインスタンス化するときにOCCIがコールするいくつかのメソッドと、マッピングを環境に登録するためにOCCIアプリケーションでコールされる関数も実装しています。これらの宣言は、使用しているOCCIアプリケーションにインクルード(#include
)するヘッダー・ファイルに格納されます。マッピングを登録する関数のプロトタイプは、OCCIアプリケーションにもインクルードされる独立したヘッダー・ファイルに記述されます。メソッド実装は、OCCIアプリケーションにリンクされているC++ソース・コード・ファイル(拡張子.cpp
)に格納されます。マッピングを登録する関数は、アプリケーションにもリンクされている独立したC++ (xxx
.cpp
)ファイルに格納されます。
図8-1は、OTTユーティリティをOCCIで使用する場合のステップを示しています。これらのステップは、次の図の後に説明します。
SQL DLLを使用してデータベースに型定義を作成します。
OTTユーティリティで変換するデータベース型が含まれたINTYPE
ファイルを作成します。
C++が生成されるように指定し、OTTユーティリティを起動します。
OTTユーティリティは、次のファイルを生成します。
オブジェクト型のC++クラス表現が含まれたヘッダー・ファイル(拡張子.h
)。ファイル名は、HFILE
パラメータによって、OTTコマンドラインに指定されます。
マッピングを登録する関数(MAPFUNC
)のプロトタイプが含まれたヘッダー・ファイル。
オブジェクトをインスタンス化している間にOCCIがコールする静的メソッドが含まれたC++ソース・ファイル(拡張子.cpp
)。ファイル名は、CPPFILE
パラメータによって、OTTコマンドラインに指定されます。これらのメソッドは、使用しているOCCIアプリケーションから直接コールしないでください。
マッピングを環境に登録するために使用する関数が含まれたファイル(拡張子.cpp
)。ファイル名は、MAPFILE
パラメータによって、OTTコマンドラインに指定されます。
バージョン文字列や変換結果を書き込むファイルなど、変換された各型のエントリが含まれたファイル(OUTTYPE
ファイル)。ファイル名は、OUTTYPE
パラメータによって、OTTコマンドラインに指定されます。
OCCIアプリケーションを記述し、OTTユーティリティで作成されたヘッダー・ファイルをOCCIソース・コード・ファイルにインクルードします。
アプリケーションで環境を宣言し、関数MAPFUNC
をコールしてマッピングを登録します。
OCCIアプリケーションをコンパイルしてOCCIオブジェクト・コードを作成し、そのオブジェクト・コードをOCCIライブラリにリンクしてプログラム実行可能ファイルを作成します。
OTTユーティリティによって、データベース・オブジェクト型からC++クラスが生成されると、そのクラスの宣言には、オブジェクト型の各属性に対応する1つの要素が含まれます。属性のデータ型は、表8-2に定義されているように、Oracleオブジェクト・データ型で使用される型にマッピングされます。
各クラスごとに、2つのnew演算子、readSQL()
メソッドおよびwriteSQL()
メソッドが生成されます。これらは、オブジェクトのマーシャリングおよびアンマーシャリングの際にOCCIによって使用されます。
デフォルトでは、オブジェクト型に対してOTTユーティリティが生成したC++クラスはPObject
クラスから導出されるため、生成されたそのクラス内のコンストラクタもPObject
クラスから導出されます。継承されたデータベース型の場合、クラスは、生成されたコンストラクタのように親の型のクラスから導出され、親のクラスにはない属性に対応する要素のみが含まれます。
データベース型の属性に対応する要素を含むクラス宣言およびメソッド宣言は、OTTユーティリティによって生成されたヘッダー・ファイルに含まれます。メソッド実装は、OTTユーティリティによって生成されたCPPFILE
ファイルに含まれます。
例8-14 OTTユーティリティを使用してC++クラスを生成する方法
この例は、OTTユーティリティを使用してC++クラスを生成する方法を示しています。
型を定義します。
CREATE TYPE FULL_NAME AS OBJECT (first_name CHAR(20), last_name CHAR(20)); CREATE TYPE ADDRESS AS OBJECT (state CHAR(20), zip CHAR(20)); CREATE TYPE ADDRESS_TAB AS VARRAY(3) of REF ADDRESS; CREATE TYPE PERSON AS OBJECT (id NUMBER, name FULL_NAME, curr_addr REF ADDRESS, prev_addr_l ADDRESS_TAB) NOT FINAL; CREATE TYPE STUDENT UNDER PERSON (school_name CHAR(20));
INTYPE
ファイルを準備します。
CASE = SAME MAPFILE = RegisterMappings_3.cpp TYPE FULL_NAME AS FullName TRANSLATE first_name as FirstName last_name as LastName TYPE ADDRESS TYPE PERSON TYPE STUDENT
OTTユーティリティを起動します。
ott userid=demousr intype=demoin_3.typ outype=demoout_3.typ code=cpp hfile=demo_3.h cppfile=demo_3.cpp
マッピングを環境に登録する関数はOTTユーティリティによって生成されます。この関数には、OTTユーティリティの起動によって変換されるすべての型に対するマッピングが含まれています。関数の名前はMAPFUNC
パラメータで指定されるか、その指定のない場合にはMAPFILE
パラメータから導出されます。関数への引数は、Environment
へのポインタのみです。
この関数は、指定されたEnvironment
を使用してMap
を取得し、変換した各タイプのマッピングを登録します。
OTTユーティリティによって生成されたクラスの機能を拡張するために、新しいクラスを導出できます。メソッドをクラスに追加することもできますが、内在するリスクがあるため、お薦めしません。
CAddress
クラスとMyAddress
クラスの両方をSQLオブジェクト型ADDRESS
から生成するには、MyAddress
クラスをCAddress
クラスから導出できます。OTTユーティリティは、生成するコードを次の方法で変更する必要があります。
CAddress
クラスのかわりにMyAddress
クラスを使用して、データ型がADDRESS
の属性を表現します。
CAddress
クラスのかわりにMyAddress
クラスを使用して、データ型がADDRESS
のベクターおよびREF
の要素を表現します。
ADDRESS
から継承されるデータベース・オブジェクト型のベース・クラスとして、CAddress
クラスのかわりにMyAddress
クラスを使用します。導出クラスがMyAddress
のサブタイプである場合でも、コールされたreadSQL
()メソッドとwriteSQL()
メソッドは、CAddress
クラスのメソッドです。
注意: クラスが拡張されて、かつ他の生成クラスのベース・クラスとして使用される場合には、継承する型のクラスと継承される型のクラスが別のファイルに生成される必要があります。 |
例8-15 OTTユーティリティを使用してC++クラスを拡張する方法
OTTユーティリティを使用してCAddress
クラス(MyAddress
クラスから導出)を生成するには、TYPE
文に次の句を指定する必要があります。
TYPE ADDRESS GENERATE CAdress AS MyAddress
以前に作成したFULL_NAME
、ADDRESS
、PERSON
およびPFGRFDENT
のデータベース型を指定し、INTYPE
ファイルを変更してGENERATE...
AS
句を挿入します。
CASE = SAME MAPFILE = RegisterMappings_5.cpp TYPE FULL_NAME GENERATE CFullName AS MyFullName TRANSLATE first_name as FirstName last_name as LastName TYPE ADDRESS GENERATE CAddress AS MyAddress TYPE PERSON GENERATE CPerson AS MyPerson TYPE STUDENT GENERATE CStudent AS MyStudent
OTT生成コードの機能を拡張するために、プログラマはOTT生成ファイルにコードを追加する場合があります。OTTは、事前定義されたマーカー(タグ)を検索することによって、OTT生成コードとユーザーが追加したコードを区別します。OTTでは、OTT_USERCODE_START
を「ユーザー・コード・マーカーの開始」、OTT_USERCODE_END
を「ユーザー・コード・マーカーの終了」と認識します。
OTTマーカーをサポートするため、ユーザー・ブロックは次のように定義されます。
OTT_USERCODE_START + user added code + OTT_USERCODE_END
OTTマーカーのサポートによって、*.hファイルおよび*.cppファイルのユーザーが追加したブロックを引き継ぐことができます。
次の各項では、OTTマーカーのサポートのプロパティについて説明します。
ユーザーは、ファイルを生成するために最初にOTTを起動するときから、コマンドライン・オプションUSE_MARKER=TRUE
を使用する必要があります。
ユーザーは、マーカーを他のC++文と同様に処理する必要があります。コマンドライン・オプションUSE_MARKER=TRUE
の使用時に、マーカーはOTTによって生成済ファイル内に次のように定義されます。
#ifndef OTT_USERCODE_START #define OTT_USERCODE_START #endif #ifndef OTT_USERCODE_END #define OTT_USERCODE_END #endif
マーカーのOTT_USERCODE_START
およびOTT_USERCODE_END
の前後には空白が必要です。
OTTは、次回のコード生成時に、マーカーに囲まれた指定のテキスト/コードをコピーします。
ユーザーが変更したコード:
1 // --- modified generated code 2 OTT_USERCODE_START 3 // --- including "myfullname.h" 4 #ifndef MYFULLNAME_ORACLE 5 #include "myfullname.h" 6 #endif 7 OTT_USERCODE_END 8 // --- end of code addition
引き継がれるコード:
1 OTT_USERCODE_START 2 // --- including "myfullname.h" 3 #ifndef MYFULLNAME_ORACLE 4 #include "myfullname.h" 5 #endif 6 OTT_USERCODE_END
次の例に示すように、データベースのTYPE
ファイルまたはINTYPE
ファイルが変更されると、OTTでは、ユーザーが追加したコードを正しく引き継ぎません。
ユーザーがタイプ名の大/小文字を変更すると、OTTでは、ユーザーがINTYPE
ファイル内のクラス名の大/小文字を変更する前にコードが関連付けられていたクラス名の判断に失敗します。
CASE=UPPER CASE=LOWER
TYPE employee TYPE employee
TRANSLATE SALARY$ AS salary TRANSLATE SALARY$ AS salary
DEPTNO AS department DEPTNO AS department
TYPE ADDRESS TYPE ADDRESS
TYPE item TYPE item
TYPE "Person" TYPE "Person"
TYPE PURCHASE_ORDER AS p_o TYPE PURCHASE_ORDER AS p_o
ユーザーが別の名前でクラスを生成するように要求した場合(INTYPE
ファイルのGENERATE AS
句)、OTTでは、ユーザーがINTYPE
ファイル内のクラス名を変更する前にコードが関連付けられていたクラス名の判断に失敗します。
CASE=LOWER CASE=LOWER TYPE employee TYPE employee TRANSLATE SALARY$ AS salary TRANSLATE SALARY$ AS salary DEPTNO AS department DEPTNO AS department TYPE ADDRESS TYPE ADDRESS TYPE item TYPE item TYPE "Person" TYPE "Person" TYPE PURCHASE_ORDER AS p_o TYPE PURCHASE_ORDER AS purchase_order
OTTで.h
ファイルまたは.cpp
ファイルの解析中にエラーが発生した場合、そのエラーはレポートされ、ファイルはエラーが発生した状態のままになります。これによって、ユーザーは、レポートされたエラーを修正し、OTTを再実行できます。
OTTでは、次の場合にエラーが発生します。
OTT_USERCODE_START
に対応するOTT_USERCODE_END
が検出されない場合
マーカーがネストされている場合(OTTで、前のOTT_USERCODE_START
に対応するOTT_USERCODE_END
が検出される前に、次のOTT_USERCODE_START
が検出された場合)
OTT_USERCODE_START
の前にOTT_USERCODE_END
が検出された場合
ユーザーは、マーカーのサポートを有効にするために、コマンドライン・オプションUSE_MARKER=TRUE
を使用する必要があります。ユーザーが追加したコードをOTTマーカーが引き継ぐには、一般的には2つの方法があります。
.hファイルにユーザー・コードを追加する場合。
グローバル・スコープにユーザー・コードを追加する場合。通常は、ユーザーが別のヘッダー・ファイルを組み込んだり宣言を転送する必要がある場合です。後のコード例を参照してください。
クラス宣言にユーザー・コードを追加する場合。OTT生成のクラス宣言に、データ・メンバー用のプライベート・スコープとメソッド用のパブリック・スコープがある場合、またはデータ・メンバー用の保護付きスコープとメソッド用のパブリック・スコープがある場合です。ユーザー・ブロックは、OTT生成のすべての宣言の後、いずれかのアクセス指定子内に追加できます。
例8-16 OTTユーティリティを使用してユーザー・コードをヘッダー・ファイルに追加する方法
... #ifndef OTT_USERCODE_START #define OTT_USERCODE_START #endif #ifndef OTT_USERCODE_END #define OTT_USERCODE_END #endif #ifndef OCCI_ORACLE #include <occi.h> #endif OTT_USERCODE_START // user added code ... OTT_USERCODE_END #ifndef ... // OTT generated include #include " ... " #endif OTT_USERCODE_START // user added code ... OTT_USERCODE_END class <class_name_1> : public oracle::occi::PObject { protected: ... // OTT generated data members OTT_USERCODE_START // user added code for data member / method ... // declaration / inline method OTT_USERCODE_END public: void *operator new(size_t size); ... OTT_USERCODE_START // user added code for data member / method ... // declaration / inline method definition OTT_USERCODE_END }; OTT_USERCODE_START // user added code ... OTT_USERCODE_END class <class_name_2> : public oracle::occi::PObject { ... }; OTT_USERCODE_START // user added code ... OTT_USERCODE_END ... #endif // end of .h file
.cppファイルにユーザー・コードを追加する場合。OTTでは、新規のユーザー定義メソッドをOTTマーカー内に追加できます。ユーザー・ブロックは、ファイルの先頭部分で、インクルード(include)の直後、かつOTT生成メソッドの定義の前に追加する必要があります。OTT生成のインクルード(include
)が複数ある場合、ユーザー・コードは、それらのOTT生成のインクルードの間にも追加できます。xxx
.cpp
ファイル内のこれ以外の位置に追加されたユーザー・コードは引き継がれません。
例8-17 OTTユーティリティを使用してユーザー・コードをソース・ファイルに追加する方法
#ifndef OTT_USERCODE_START #define OTT_USERCODE_START #endif #ifndef OTT_USERCODE_END #define OTT_USERCODE_END #endif ... OTT_USERCODE_START // user added code ... OTT_USERCODE_END ... OTT_USERCODE_START // user added code ... OTT_USERCODE_END /************************************************************* / generated method implementations for the ... object type. /*************************************************************/ void *<class_name_1>::operator new(size_t size) { return oracle::occi::PObject::operator new(size); } ... // end of .cpp file