Object Type Translator(OTT)は、オブジェクト型と名前付きコレクション型のデータベース定義を、OCIまたはPro*C/C++アプリケーションにインクルードできるC言語の構造体宣言に変換します。
OCIとPro*C/C++のプログラマは、OTTを明示的に起動してデータベース型をC言語の表現に変換する必要があります。また、OCIのプログラマは、タイプ・バージョン表と呼ばれるデータ構造を、プログラムに必要なユーザー定義型の情報で初期化する必要があります。この初期化を実行するためのコードは、OTTによって生成されます。Pro*C/C++では、型のバージョン情報は、Pro*C/C++にパラメータとして渡されるOUTTYPE
ファイルに記録されます。
ほとんどのオペレーティング・システムでは、コマンドラインからOTTを起動します。OTTは、INTYPE
ファイルを入力として受け取り、OUTTYPE
ファイル、1つ以上のC言語のヘッダー・ファイルおよびオプションの実装ファイル(OCIプログラマ用)を生成します。OTTを起動するコマンドの例を次に示します。
ott userid=scott/tiger intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h
このコマンドを実行すると、OTTはユーザー名scottとパスワードtigerを使用してデータベースに接続され、INTYPE
ファイルdemoin.typ
内の指示に従ってデータベース型をC言語の構造体に変換します。その結果、構造体はCODE パラメータで指定したホスト言語(C)用に、ヘッダー・ファイルdemo.h
に出力されます。OUTTYPE
ファイルdemoout.typ
には、この変換に関する情報が格納されます。
各パラメータについては、この章のこの後の項で詳しく説明します。
demoin.typ
ファイルの例:
CASE=LOWER TYPE employee
demoout.typ
ファイルの例:
CASE = LOWER TYPE SCOTT.EMPLOYEE AS employee VERSION = "$8.0" HFILE = demo.h
この例では、demoin.typ
ファイルに、TYPEが前に付く変換対象の型(TYPE employeeなど)があります。OUTTYPE
ファイルの構造はINTYPE
ファイルに似ていますが、OTTが取得した情報が追加されています。
OTTによる変換が完了すると、ヘッダー・ファイルにはINTYPE
ファイルで指定した各型を表すC言語の構造体と、各型に対応するNULLインジケータ構造体が含まれています。たとえば、INTYPE
ファイルにリストされたemployee型が次のように定義されたとします。
CREATE TYPE employee AS OBJECT ( name VARCHAR2(30), empno NUMBER, deptno NUMBER, hiredate DATE, salary NUMBER );
この場合、OTTによって生成されるヘッダー・ファイル(demo.h
)には、他の項目とともに次の宣言が含まれます。
struct employee { OCIString * name; OCINumber empno; OCINumber deptno; OCIDate hiredate; OCINumber salary; }; typedef struct emp_type emp_type; struct employee_ind { OCIInd _atomic; OCIInd name; OCIInd empno; OCIInd deptno; OCIInd hiredate; OCIInd salary; }; typedef struct employee_ind employee_ind;
構造体宣言で使用されるデータ型(OCIString、OCIIndなど)はOracle8の新しい特殊データ型です。これらの型の詳細は、OTTデータ型のマッピングを参照してください。
これ以降の項では、OTTの使用について次の事柄を説明します。
次の各項では、OTTをOCIおよびPro*C/C++とともに使用する方法について説明してから、参考のためにコマンドライン構文、パラメータ、INTYPE
ファイルの構造、ネストされた#include
ファイルの生成、スキーマ名の使用方法、デフォルト名のマッピングおよび制限事項について説明します。
OTTを使用するときの最初のステップは、オブジェクト型または名前付きコレクション型を作成してデータベースに格納することです。そのためには、SQL CREATE TYPE文を使用します。
関連項目: オブジェクト型およびコレクション型の作成方法の詳細は、オブジェクトを参照してください。
OTTを起動するステップは、次のとおりです。
OTTのパラメータは、コマンドラインまたは構成ファイル内で指定できます。一部のパラメータはINTYPE
ファイルでも指定できます。
パラメータを数箇所で指定すると、優先順位が最も高いのはコマンドラインで指定した値で、次にINTYPE
ファイル内の値、ユーザー定義の構成ファイルの値、デフォルトの構成ファイル内の値の順になります。
グローバル・オプション、つまりコマンドラインのオプションまたはINTYPE
ファイルのTYPE文の前のオプションについては、INTYPE
ファイルの値が上書きされます。(INTYPE
ファイルでグローバルとして指定できるオプションには、CASE
、CODE
、INITFILE
、OUTDIR
およびINITFUNC
があります。HFILE
は含まれません。)TYPEを指定するINTYPE
ファイルのオプションは、特定の型にのみ適用されます。その型に適用される、コマンドラインで指定したそれ以外のオプションは上書きされます。TYPE person HFILE=p.h
と入力した場合、オプションはperson
にのみ適用され、コマンドラインのHFILE
は上書きされます。文はコマンドライン・パラメータとはみなされません。
コマンドラインに設定されたパラメータ(オプションとも呼ばれます)は、他で設定されたパラメータを上書きします。
関連項目: オブジェクト型およびコレクション型の作成方法の詳細は、オブジェクトを参照してください。
構成ファイルは、OTTパラメータが記述されているテキスト・ファイルです。ファイル内の非空白行には、1つのパラメータと、それに対応付けられた1つ以上の値が入っています。1行に2つ以上のパラメータを指定した場合は、最初のパラメータのみが使用されます。構成ファイルの非空白行では、空白は使用できません。
構成ファイルは、コマンドラインで名前を指定できます。また、デフォルトの構成ファイルは常に読み取られます。このデフォルトの構成ファイルは、常に存在している必要がありますが、空でも構いません。デフォルトの構成ファイルの名前はottcfg.cfg
であり、構成ファイルの位置はシステム固有の設定です。詳細は、プラットフォーム固有のマニュアルを参照してください。
INTYPE
ファイルは、OTTにより変換される型のリストを示します。
パラメータCASE
、HFILE
、INITFUNC
およびINITFILE
は、INTYPE
ファイルに入れることができます。詳細は、INTYPEファイルを参照してください。
ほとんどのプラットフォームでは、OTTはコマンドラインから起動します。入力ファイル、出力ファイルおよびデータベース接続情報などを指定できます。プラットフォームでOTTを起動する方法は、プラットフォーム固有のマニュアルで確認してください。
次の例(例1)は、コマンドラインからOTTを起動する方法を示しています。
ott userid=scott/tiger intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h
注意:
等号(=)の前後には空白は入力できません。
次の各項では、この例で使用しているコマンドラインの要素を説明します。
OTTコマンドラインの様々なオプションの詳細は、OTT参照を参照してください。
OUTTYPE
ファイルの名前を指定します。OTTは、C言語のヘッダー・ファイルを生成するときに、変換対象の型の情報をOUTTYPE
ファイルにも書き込みます。このファイルには、変換された各型のエントリが、バージョン文字列およびC表現を書き込んだヘッダー・ファイルとともに含まれています。
例1では、OUTTYPEファイルの名前をdemoout.typ
と指定しています。
注意:
OUTTYPE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
変換のターゲット言語を指定します。次のオプションを使用できます。
C (ANSI_Cと等価)
ANSI_C (ANSI C対応)
KR_C (Kernighan & Ritchie C対応)
現在、デフォルト値はないため、このパラメータは必須です。
構造体の宣言は、両方のC言語において同一です。INITFILE
ファイルで定義された初期化関数が定義されるスタイルは、KR_Cが使用されるかどうかによって決まります。INITFILE
オプションが使用されていない場合、3つのオプションはすべて等価です。
生成された構造体を書き込むCヘッダー・ファイルの名前を指定します。例1では、生成された構造体はファイルdemo.h
に格納されます。
注意:
HFILE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
型初期化関数を書き込むCソース・ファイルの使用を指定します。
初期化関数は、OCIプログラム内でのみ必要です。Pro*C/C++プログラムでは、Pro*C/C++ランタイム・ライブラリによって型が自動的に初期化されます。
注意:
OUTTYPE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
OTTの実行時に、INTYPE
ファイルはどのデータベース型の変換が必要であるかをOTTに指示します。また、このファイルを使用して、生成される構造体の命名方法も指定できます。INTYPE
ファイルは、新しく作成しても、前にOTTを起動したときのOUTTYPE
ファイルを使用してもかまいません。INTYPE
パラメータが使用されていない場合は、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構造体になります。これらの構造体のメンバーは、小文字で名前が付けられます。
CASE
オプションの詳細は、CASEを参照してください。
TYPEキーワードで始まる行では、データベース内のどの型を変換するかを指定します。この場合、EMPLOYEE、ADDRESS、ITEM、PERSONおよびPURCHASE_ORDER型です。
TRANSLATE...ASキーワードでは、オブジェクト型をC言語の構造体に変換するときに、オブジェクト属性の名前を変更するように指定しています。この場合は、employee
型のSALARY$属性がsalary
に変換されます。
最終行のASキーワードでは、オブジェクト型を構造体に変換するときに、名前を変更するように指定しています。この例では、purchase_orderというデータベース型をp_oという構造体に変換します。
ASを使用して型や属性名を変換しなければ、その型や属性のデータベース名がC言語の識別子名として使用されます。ただし、CASE
オプションを指定した場合、有効なC言語の識別子文字にマップできない文字は、アンダースコアに置換されます。型または属性名を変換する理由は、次のとおりです。
名前に、アルファベット、数字およびアンダースコア以外の文字が含まれる場合
名前がC言語のキーワードと競合する場合
型名が、同じ有効範囲内の別の識別子と競合する。たとえば、プログラムで、異なるスキーマにある同じ名前の2つの型を使用する場合に発生します。
プログラマが別の名前に変更する場合。
OTTでは、INTYPE
ファイル内で指定されていない型の変換が必要な場合があります。これは、OTTでは、変換の実行前にINTYPE
ファイル内の型相互の依存性が分析され、必要であれば他の型も変換されるためです。たとえば、ADDRESS型が
INTYPE
ファイルにリストされていなくても、Person型がADDRESS型の属性を所有している場合、Person型の定義は必須のため、OTTは、ADDRESSを変換します。
注意:
リリース1(9.0.1)以降では、TRANSITIVE = FALSEを指定することにより、INTYPE
ファイルに指定されていない型が生成されないようにできます。デフォルトでは、TRANSITIVEはTRUEに設定されます。
通常の大/小文字の区別がないSQL識別子は、INTYPE
ファイルで、大/小文字のどのような組合せのつづりでもかまいません。そして、引用符は付けません。
CREATE TYPE "Person"などの大/小文字を区別して作成したSQL識別子を参照するには、TYPE "Person"などの引用符を使用します。宣言されたときに引用符が付けられたSQL識別子では、大/小文字が区別されます。
また、引用符は、TYPE "CASE"のようにOTT予約語であるSQL識別子を参照するためにも使用できます。この場合、そのSQL識別子がCREATE TYPE Caseのように大/小文字を区別しないで作成されていれば、名前に引用符を付けるときは、その名前を大文字にする必要があります。SQL識別子名を参照するために使用するOTT予約語に引用符を付けなければ、INTYPE
ファイル内で構文エラーがレポートされます。
関連項目: INTYPE
ファイル構造の仕様の詳細と使用可能なオプションは、INTYPEファイルの構造を参照してください。
OTTでデータベース型から生成したC構造体には、オブジェクト型の属性ごとに1つずつ対応する要素が含まれています。属性のデータ型は、Oracleのオブジェクト型で使用される型にマップされます。オブジェクト型やコレクションなどのユーザー定義型の作成をサポートするために、Oracleのデータ型には、事前定義済のプリミティブ型の集合が組み込まれています。
一連の事前定義の型には、数値型や文字型を含む、プログラマによく知られている標準の型があります。また、Oracle8で新しく導入されたデータ型(BLOBやCLOBなど)もあります。
Oracleには、オブジェクト型の属性をC言語の構造体で表すための事前定義済の型のセットも用意されています。たとえば、次のようなオブジェクト型定義と、OTTで生成した対応する構造体宣言があるとします。
CREATE TYPE employee AS OBJECT ( name VARCHAR2(30), empno NUMBER, deptno NUMBER, hiredate DATE, salary$ NUMBER);
CASE=LOWER
で、型または属性名の明示的なマッピングがないと仮定すると、OTT出力は次のようになります。
struct employee { OCIString * name; OCINumber empno; OCINumber department; OCIDate hiredate; OCINumber salary_; }; typedef struct emp_type emp_type; struct employee_ind { OCIInd _atomic; OCIInd name; OCIInd empno; OCIInd department; OCIInd hiredate; OCIInd salary_; } typedef struct employee_ind employee_ind;
インジケータ構造体(struct employee_ind
)については、NULLインジケータ構造体を参照してください。
構造体宣言のデータ型OCIString
、OCINumber
、OCIDate
、OCIInd
はOracle8の新しいオブジェクト型のCマッピングです。オブジェクト型属性のデータ型をマップするためにここで使用されます。たとえば、empno
属性のNUMBER
データ型は、新しいOCINumber
データ型にマップします。また、これらの新しいデータ型は、バインド変数および定義変数の型としても使用します。
関連項目: OCIアプリケーションのオブジェクト・データ型を含むデータ型の使用方法の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。
この項では、オブジェクトの属性型をOTTによって生成されたC言語のデータ型にマップする方法について説明します。様々なマッピングの例については、OTT型マッピングの例を参照してください。表19-1は、OTTによって生成されるオブジェクト・データ型の属性として使用できる型からのマッピングを示しています。
表19-1 オブジェクト型属性のオブジェクト・データ型マッピング
オブジェクト属性の型 | Cマッピング |
---|---|
VARCHAR2(N) |
OCIString * |
VARCHAR(N) |
OCIString * |
CHAR(N)、CHARACTER(N) |
OCIString * |
NUMBER、NUMBER(N)、NUMBER(N,N) |
OCINumber |
NUMERIC、NUMERIC(N)、NUMERIC(N,N) |
OCINumber |
REAL |
OCINumber |
INT、INTEGER、SMALLINT |
OCINumber |
FLOAT、FLOAT(N)、DOUBLE PRECISION |
OCINumber |
DEC、DEC(N)、DEC(N,N) |
OCINumber |
DECIMAL、DECIMAL(N)、DECIMAL(N,N) |
OCINumber |
DATE |
OCIDate * |
BLOB |
OCIBlobLocator * |
CLOB |
OCIClobLocator * |
BFILE |
OCIBFileLocator * |
ネストされたオブジェクト型 |
ネストされたオブジェクト型のC言語名。 |
REF |
typedefを使用して宣言。OCIRef *に相当。 |
RAW(N) |
OCIRaw * |
表19-2は、名前付きのコレクション型の、OTTによって生成されるオブジェクト・データ型へのマッピングを示しています。
表19-2 コレクション型のオブジェクト・データ型マッピング
名前付きコレクション型 | Cマッピング |
---|---|
VARRAY |
typedefを使用して宣言。OCIArray *に相当。 |
NESTED TABLE |
typedefを使用して宣言。OCITable *に相当。 |
注意:
REF、VARRAYおよびNESTED TABLE型では、OTTによりtypedefが生成されます。このtypedefで宣言された型は、構造体宣言でデータ・メンバーの型として使用されます。例は、OTT型マッピングの例を参照してください。
オブジェクト型にREFまたはコレクション型の属性が含まれる場合は、最初にREFまたはコレクション型のtypedefが生成されます。次に、オブジェクト型に対応する構造体宣言が生成されます。構造体には、REFまたはコレクション型へのポインタを型に持つ要素が含まれます。
あるオブジェクト型に、別のオブジェクト型を持つ属性が含まれている場合、OTTではネストした型が最初に生成されます(TRANSITIVE=TRUEの場合。)次に、オブジェクト型属性が、ネストしたオブジェクト型である型のネストした構造体にマッピングされます。
OTTによってオブジェクトではないデータベース属性型がマップされるC言語のデータ型は、構造体です。ただし、OCIDateの場合は不明になります。
次の例は、OTTによって作成される各種の型のマッピングを示しています。
この例では、次のデータベース型を使用します。
CREATE TYPE my_varray AS VARRAY(5) of integer; CREATE TYPE object_type AS OBJECT (object_name VARCHAR2(20)); 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
OTTでは、次のC言語の構造体が生成されます。
注意:
構造体の説明の補足コメントを次に示します。これらのコメントは、実際のOTT出力の一部ではありません。
#ifndef MYFILENAME_ORACLE #define MYFILENAME_ORACLE #ifndef OCI_ORACLE #include <oci.h> #endif typedef OCIRef many_types_ref; typedef OCIRef object_type_ref; typedef OCIArray my_varray; /* part of many_types */ typedef OCITable my_table; /* part of many_types*/ typedef OCIRef other_type_ref; struct object_type /* part of many_types */ { OCIString * object_name; }; typedef struct object_type object_type; struct object_type_ind /*indicator struct for*/ { /*object_types*/ OCIInd _atomic; OCIInd object_name; }; typedef struct object_type_ind object_type_ind; struct many_types { OCIString * the_varchar; OCIString * the_char; OCIBlobLocator * the_blob; OCIClobLocator * the_clob; struct object_type the_object; other_type_ref * another_ref; many_types_ref * the_ref; my_varray * the_varray; my_table * the_table; OCIDate the_date; OCINumber the_num; OCIRaw * the_raw; }; typedef struct many_types many_types; struct many_types_ind /*indicator struct for*/ { /*many_types*/ OCIInd _atomic; OCIInd the_varchar; OCIInd the_char; OCIInd the_blob; OCIInd the_clob; struct object_type_ind the_object; /*nested*/ OCIInd another_ref; OCIInd the_ref; OCIInd the_varray; OCIInd the_table; OCIInd the_date; OCIInd the_num; OCIInd the_raw; }; typedef struct many_types_ind many_types_ind; #endif
INTYPE
ファイル内で指定した変換対象の項目は1つのみですが、2つのオブジェクト型と2つの名前付きコレクション型が変換されていることに注目してください。これは、OTTパラメータTRANSITIVEのデフォルト値がTRUEであるためです。該当する項の説明にあるとおり、TRANSITIVE=TRUEの場合、指定された型の変換を完了するために、OTTは変換対象の型の属性として使用される型をすべて自動的に変換します。
ただし、その型がオブジェクト型属性内でポインタまたはREFでしかアクセスされない場合は例外です。たとえば、many_types型には属性としてanother_ref
がありますが、
REF other_typestruct other_type
は生成されません。
また、この例では、VARRAY、NESTED TABLEおよびREFの各型を宣言するためのtypedefの使用方法を示しています。
typedefは、始めに使用されます。
typedef OCIRef many_types_ref; typedef OCIRef object_type_ref; typedef OCIArray my_varray; typedef OCITable my_table; typedef OCIRef other_type_ref;
構造体many_types
では、次のようにVARRAY、NESTED TABLEおよびREF属性が宣言されています。
struct many_types { ... other_type_ref * another_ref; many_types_ref * the_ref; my_varray * the_varray; my_table * the_table; ... }
OTTによってデータベース・オブジェクト・タイプを表すC言語の構造体が生成されるたびに、それに対応するNULLインジケータ構造体も生成されます。あるオブジェクト型をC言語の構造体に変換すると、NULLインジケータ情報をパラレル構造体に変換できます。
たとえば、前の項の例では次のNULLインジケータ構造体が生成されました。
struct many_types_ind { OCIInd _atomic; OCIInd the_varchar; OCIInd the_char; OCIInd the_blob; OCIInd the_clob; struct object_type_ind the_object; OCIInd another_ref; OCIInd the_ref; OCIInd the_varray; OCIInd the_table; OCIInd the_date; OCIInd the_num; OCIInd the_raw; }; typedef struct many_types_ind many_types_ind;
NULL構造体のレイアウトは重要です。構造体の第1要素(_atomic
)は、アトミックNULLインジケータです。この値は、オブジェクト型全体のNULL状態を示します。このアトミックNULLインジケータの後に、OTTで生成した、オブジェクト型を表現する構造体の各要素に対応するインジケータ要素が続きます。
あるオブジェクト型の定義の一部として別のオブジェクト型が含まれている場合(この例ではobject_type属性)、その属性のインジケータ・エントリは、ネストしたオブジェクト型に対応しているNULLインジケータ構造体(
object_type_ind
)です。
VARRAYとNESTED TABLEには、要素に関するNULL情報が含まれます。NULLインジケータ構造体のその他の要素のデータ型は、すべてOCIInd
です。
関連項目: アトミックNULLの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』のオブジェクト型の説明を参照してください。
オブジェクトの型の継承をサポートするために、OTTは、新しい属性を宣言する前に、継承される属性を、特別な名前_superを持つカプセル化された構造体内で宣言することで、オブジェクトのサブタイプを表すC構造体を生成します。これによって、スーパータイプを継承するオブジェクトのサブタイプについては、その構造体の第1要素が'_super'と命名され、サブタイプの各属性に対応する要素がその後に続きます。名前'_super'が付いた要素の型は、スーパータイプの名前です。
たとえば、サブタイプStudent_t
とEmployee_t
を持つPerson_t
型は、次のように作成されます。
CREATE TYPE Person_t AS OBJECT ( ssn NUMBER, name VARCHAR2(30), address VARCHAR2(100)) NOT FINAL; CREATE TYPE Student_t UNDER Person_t ( deptid NUMBER, major VARCHAR2(30)) NOT FINAL; CREATE TYPE Employee_t UNDER Person_t ( empid NUMBER, mgr VARCHAR2(30));
また、INTYPE
ファイルに次が含まれているとします。
CASE=SAME TYPE EMPLOYEE_T TYPE STUDENT_T TYPE PERSON_T
OTTでは、Person_t
、Student_t
およびEmployee_t
の次のC言語の構造体と、そのNULLインジケータ構造体が生成されます。
#ifndef MYFILENAME_ORACLE #define MYFILENAME_ORACLE #ifndef OCI_ORACLE #include <oci.h> #endif typedef OCIRef EMPLOYEE_T_ref; typedef OCIRef STUDENT_T_ref; typedef OCIRef PERSON_T_ref; struct PERSON_T { OCINumber SSN; OCIString * NAME; OCIString * ADDRESS; }; typedef struct PERSON_T PERSON_T; struct PERSON_T_ind { OCIInd _atomic; OCIInd SSN; OCIInd NAME; OCIInd ADDRESS; }; typedef struct PERSON_T_ind PERSON_T_ind; struct EMPLOYEE_T { PERSON_T _super; OCINumber EMPID; OCIString * MGR; }; typedef struct EMPLOYEE_T EMPLOYEE_T; struct EMPLOYEE_T_ind { PERSON_T _super; OCIInd EMPID; OCIInd MGR; }; typedef struct EMPLOYEE_T_ind EMPLOYEE_T_ind; struct STUDENT_T { PERSON_T _super; OCINumber DEPTID; OCIString * MAJOR; }; typedef struct STUDENT_T STUDENT_T; struct STUDENT_T_ind { PERSON_T _super; OCIInd DEPTID; OCIInd MAJOR; }; typedef struct STUDENT_T_ind STUDENT_T_ind; #endif
前述のCマッピングの変換により、C言語でのサブタイプのインスタンスからスーパータイプのインスタンスへの単純な上位キャストが正常に機能します。次に例を示します。
STUDENT_T *stu_ptr = some_ptr; /* some STUDENT_T instance */ PERSON_T *pers_ptr = (PERSON_T *)stu_ptr; /* up-casting */
同様にNULLインジケータ構造体が生成されます。スーパータイプPerson_t
のNULLインジケータ構造体の最初の要素は_atomicで、サブタイプEmployee_t
およびStudent_t
のNULLインジケータ構造体の最初の要素は_superであることに注意してください(サブタイプの場合、アトミック要素は生成されません)。
NOT FINAL型の属性(したがって、潜在的に置換可能な属性)の場合、埋込み属性はポインタとして表されます。
Book_t
型が次のように作成されるとします。
CREATE TYPE Book_t AS OBJECT ( title VARCHAR2(30), author Person_t /* substitutable */);
OTTで生成された対応するC構造体には、Person_t
へのポインタが含まれています。
struct Book_t { OCIString *title; Person_t *author; /* pointer to Person_t struct */ }
前述の型に対応するNULLインジケータ構造体は、次のようになります。
struct Book_t_ind { OCIInd _atomic; OCIInd title; OCIInd author; }
author
属性に対応するNULLインジケータ構造体は、author
オブジェクト自体から取得できることに注意してください。OBJECT GETを参照してください。
型がFINALに定義されている場合、サブタイプは使用できません。したがって、FINAL型の属性は置換できません。その場合、マッピングは前述のとおりになり、属性構造体はインラインです。型が変更され、NOT FINALに定義される場合は、マッピングを変更する必要があります。新しいマッピングは、OTTを再実行すると生成されます。
OUTTYPE
ファイルは、OTTコマンドラインで名前が指定されます。OTTは、C言語のヘッダー・ファイルを生成するときに、変換結果をOUTTYPE
ファイルにも書き込みます。このファイルには、変換された各型のエントリが、バージョン文字列およびC表現を書き込んだヘッダー・ファイルとともに含まれています。
OTTを一度実行して生成したOUTTYPE
ファイルは、それ以降にOTTを起動するときのINTYPE
ファイルとして使用できます。
たとえば、この章の前半の例で使用した単純なINTYPE
ファイルを考えてみます。
CASE=LOWER TYPE employee TRANSLATE SALARY$ AS salary DEPTNO AS department TYPE ADDRESS TYPE item TYPE person TYPE PURCHASE_ORDER AS p_o
ここで、ユーザーは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
OUTTYPE
ファイルの内容を調べると、INTYPE
仕様部で指定されていなかった型がリスト表示されている場合があります。たとえば、INTYPE
ファイルでは、次の内容によるperson型の変換のみを指定したとします。
CASE = LOWER TYPE PERSON
このperson型の定義にaddress型の属性が含まれている場合、OUTTYPE
ファイルには、PERSON
とADDRESS
の両方のエントリが含まれます。person
型を完全に変換するには、最初にaddressを変換する必要があります。
パラメータTRANSITIVEをTRUE(デフォルト)に設定していると、OTTでは、変換の実行前に、INTYPE
ファイル内の型相互の依存性が分析され、必要であれば他の型も変換されます。