19 Object Type Translator
この章では、Pro*C/C++アプリケーションで使用するためにデータベース・オブジェクト・タイプ、LOB型およびコレクション型をC言語の構造体にマップする、Object Type Translator(OTT)について説明します。
この章の内容は以下のとおりです。
19.1 OTT概要
OTT(Object Type Translator)は、Oracleサーバーのユーザー定義型を利用するアプリケーションの開発に役立ちます。
SQL CREATE TYPE文を使用して、オブジェクト型を作成できます。これらの型の定義をデータベースに格納しておき、データベースの表を作成するときに使用できます。これらの表への移入後は、OCI、Pro*C/C++またはJavaのプログラマは表に格納されているオブジェクトにアクセスできます。
オブジェクト・データにアクセスするアプリケーションには、データをホスト言語形式で表現する機能が必要です。これは、オブジェクト型をC構造体として表現することによって実現できます。プログラマがデータベース・オブジェクト・タイプを表す構造体宣言を、手入力でコーディングすることは可能です。ただし、多くの型がある場合、この作業は時間がかかり、エラーを生む原因になりがちです。OTTを使用すると、必要な構造体の宣言が自動的に生成されるため、作業を軽減できます。Pro*C/C++の場合、アプリケーション側では、OTTによって生成されたヘッダー・ファイルをインクルードするのみで済みます。OCIの場合は、アプリケーション側ではOTTによって生成される初期化関数もコールする必要があります。
OTTは、格納されているデータ型を表す構造体を作成するのみでなく、オブジェクト型またはそのフィールドがNULLかどうかを示す対になるインジケータ構造体も生成します。
19.2 Object Type Translator(OTT)
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など)はOracle 8の新しい特殊データ型です。
これ以降の項では、OTTの使用について次の事柄を説明します。
次の各項では、OTTをOCIおよびPro*C/C++とともに使用する方法について説明してから、参考のためにコマンドライン構文、パラメータ、INTYPE
ファイルの構造、ネストされた#include
ファイルの生成、スキーマ名の使用方法、デフォルト名のマッピングおよび制限事項について説明します。
関連項目
19.2.1 データベースでの型の作成について
OTTを使用するときの最初のステップは、オブジェクト型または名前付きコレクション型を作成してデータベースに格納することです。そのためには、SQL CREATE TYPE文を使用します。
関連項目
19.2.2 OTTの起動について
OTTを起動するステップは、次のとおりです。
OTTのパラメータは、コマンドラインまたは構成ファイル内で指定できます。一部のパラメータはINTYPE
ファイルでも指定できます。
パラメータを数箇所で指定すると、優先順位が最も高いのはコマンドラインで指定した値で、次にINTYPE
ファイル内の値、ユーザー定義の構成ファイルの値、デフォルトの構成ファイル内の値の順になります。
グローバル・オプション、つまりコマンドラインのオプションまたはINTYPE
ファイルのTYPE文の前のオプションについては、INTYPE
ファイルの値が上書きされます。(INTYPE
ファイルでグローバルとして指定できるオプションには、CASE
、CODE
、INITFILE
、OUTDIR
およびINITFUNC
があります。HFILE
は含まれません。)TYPEを指定するINTYPE
ファイルのオプションは、特定の型にのみ適用されます。その型に適用される、コマンドラインで指定したそれ以外のオプションは上書きされます。TYPE person HFILE=p.h
と入力した場合、オプションはperson
にのみ適用され、コマンドラインのHFILE
は上書きされます。文はコマンドライン・パラメータとはみなされません。
19.2.2.2 構成ファイル
構成ファイルは、OTTパラメータが記述されているテキスト・ファイルです。ファイル内の非空白行には、1つのパラメータと、それに対応付けられた1つ以上の値が入っています。1行に2つ以上のパラメータを指定した場合は、最初のパラメータのみが使用されます。構成ファイルの非空白行では、空白は使用できません。
構成ファイルは、コマンドラインで名前を指定できます。また、デフォルトの構成ファイルは常に読み取られます。このデフォルトの構成ファイルは、常に存在している必要がありますが、空でも構いません。デフォルトの構成ファイルの名前はottcfg.cfg
であり、構成ファイルの位置はシステム固有の設定です。詳細は、プラットフォーム固有のマニュアルを参照してください。
19.2.3 OTTコマンドライン
ほとんどのプラットフォームでは、OTTはコマンドラインから起動します。入力ファイル、出力ファイルおよびデータベース接続情報などを指定できます。プラットフォームでOTTを起動する方法は、プラットフォーム固有のマニュアルで確認してください。
次の例(例1)は、コマンドラインからOTTを起動する方法を示しています。
ott userid=scott/tiger intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h
注意:
等号(=)の前後には空白は入力できません。
次の各項では、この例で使用しているコマンドラインの要素を説明します。
関連項目
19.2.3.4 OUTTYPE
OUTTYPE
ファイルの名前を指定します。OTTは、C言語のヘッダー・ファイルを生成するときに、変換対象の型の情報をOUTTYPE
ファイルにも書き込みます。このファイルには、変換された各型のエントリが、バージョン文字列およびC表現を書き込んだヘッダー・ファイルとともに含まれています。
例1では、OUTTYPEファイルの名前をdemoout.typ
と指定しています。
注意:
OUTTYPE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
19.2.3.5 CODE
変換のターゲット言語を指定します。次のオプションを使用できます。
-
C (ANSI_Cと等価)
-
ANSI_C (ANSI C対応)
-
KR_C (Kernighan & Ritchie C対応)
現在、デフォルト値はないため、このパラメータは必須です。
構造体の宣言は、両方のC言語において同一です。INITFILE
ファイルで定義された初期化関数が定義されるスタイルは、KR_Cが使用されるかどうかによって決まります。INITFILE
オプションが使用されていない場合、3つのオプションはすべて等価です。
19.2.3.6 HFILE
生成された構造体を書き込むCヘッダー・ファイルの名前を指定します。例1では、生成された構造体はファイルdemo.h
に格納されます。
注意:
HFILE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
19.2.3.7 INITFILE
型初期化関数を書き込むCソース・ファイルの使用を指定します。
初期化関数は、OCIプログラム内でのみ必要です。Pro*C/C++プログラムでは、Pro*C/C++ランタイム・ライブラリによって型が自動的に初期化されます。
注意:
OUTTYPE
で既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。
19.2.4 INTYPEファイル
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構造体になります。これらの構造体のメンバーは、小文字で名前が付けられます。
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
ファイル内で構文エラーがレポートされます。
関連項目
19.2.5 OTTデータ型のマッピング
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
データ型にマップします。また、これらの新しいデータ型は、バインド変数および定義変数の型としても使用します。
関連項目
19.2.5.1 オブジェクト・データ型のC言語へのマッピング
この項では、オブジェクトの属性型をOTTによって生成されたC言語のデータ型にマップする方法について説明します。表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で宣言された型は、構造体宣言でデータ・メンバーの型として使用されます。
オブジェクト型にREFまたはコレクション型の属性が含まれる場合は、最初にREFまたはコレクション型のtypedefが生成されます。次に、オブジェクト型に対応する構造体宣言が生成されます。構造体には、REFまたはコレクション型へのポインタを型に持つ要素が含まれます。
あるオブジェクト型に、別のオブジェクト型を持つ属性が含まれている場合、OTTではネストした型が最初に生成されます(TRANSITIVE=TRUEの場合。)次に、オブジェクト型属性が、ネストしたオブジェクト型である型のネストした構造体にマッピングされます。
OTTによってオブジェクトではないデータベース属性型がマップされるC言語のデータ型は、構造体です。ただし、OCIDateの場合は不明になります。
関連項目
19.2.5.2 OTT型マッピングの例
次の例は、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_re
REF other_typeがありますが、struct 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; ... }
19.2.6 NULLインジケータ構造体
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の詳細は、データ型のオブジェクト型の説明を参照してください。
19.2.7 OTTでの型の継承のサポート
オブジェクトの型の継承をサポートするために、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であることに注意してください(サブタイプの場合、アトミック要素は生成されません)。
19.2.7.1 置換可能なオブジェクト属性
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
オブジェクト自体から取得できることに注意してください。
型がFINALに定義されている場合、サブタイプは使用できません。したがって、FINAL型の属性は置換できません。その場合、マッピングは前述のとおりになり、属性構造体はインラインです。型が変更され、NOT FINALに定義される場合は、マッピングを変更する必要があります。新しいマッピングは、OTTを再実行すると生成されます。
関連項目
19.2.8 OUTTYPEファイル
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
ファイル内の型相互の依存性が分析され、必要であれば他の型も変換されます。
19.3 OCIアプリケーションでのOTTの使用方法
OTTによって生成されるC言語のヘッダー・ファイルと実装ファイルは、データベース・サーバーのオブジェクトにアクセスするOCIアプリケーションで使用できます。ヘッダー・ファイルをOCIコードに取込むには、#include
文を使用します。
OCIアプリケーションでは、ヘッダー・ファイルを組み込んだ後、ホスト言語形式のオブジェクト・データにアクセスし、操作できます。
図19-1は、OCIでOTTを使用する場合に必要な手順を示しています。
- SQLを使用してデータベースに型定義を作成します。
- OTTで、オブジェクト型と名前付きコレクション型のC表現を含むヘッダー・ファイルを生成します。
INITFILE
オプションで命名された実装ファイルも生成します。 - アプリケーションを記述します。OCIアプリケーションでユーザーが記述したコードで、
INITFUNC
関数を宣言してコールします。 - ヘッダー・ファイルをOCIソース・コード・ファイルにインクルードします。
- OTTで生成された実装ファイルを含めて、OCIアプリケーションがコンパイルされ、OCIライブラリにリンクされます。
- OCI実行可能ファイルをOracleサーバーに対して実行します。
19.3.1 OCIでのオブジェクトへのアクセスおよび操作について
アプリケーション内部では、OCIプログラムでバインド操作と定義操作を実行できます。そのためには、OTTで生成したヘッダー・ファイルに示されている型で宣言したプログラム変数を使用します。
たとえば、アプリケーションでSQLのSELECT文を使用してオブジェクトへのREFをフェッチし、適切なOCI関数を使用してそのオブジェクトを確保します。オブジェクトを確保した後、その他のOCI関数を使用してそのオブジェクトの属性データにアクセスし、操作できます。
OCIには、データ型のマッピングと操作のための一連の関数が組み込まれています。これらの関数は、オブジェクト型と名前付きコレクション型の属性を操作するために明確に設計されています。
次に、使用可能な関数の一部を示します。
-
OCIStringSize()
は、OCIString
文字列のサイズを取得します。 -
OCINumberAdd()
は、2つのOCINumber
数値を加算します。 -
OCILobIsEqual()
は、2つのLOBロケータが等しいかどうかを比較します。 -
OCIRawPtr()
は、OCIRaw
のRAWデータ型へのポインタを取得します。 -
OCICollAppend()
は、コレクション型(OCIArray
またはOCITable
)に要素を追加します。 -
OCITableFirst()
は、NESTED TABLE(OCITable
)の最初の既存要素の索引を戻します。 -
OCIRefIsNull()
は、REF(OCIRef
)がNULLかどうかをテストします。
これらの関数については、『Oracle Call Interfaceプログラマーズ・ガイド』の次の各章で詳しく説明しています。
-
第2章(バインドと定義付けなどのOCI概念の説明)
-
第6章(オブジェクトへのアクセスとナビゲーションの説明)
-
第7章(データ型のマップと操作の説明)
-
第12章(データ型のマップと操作の関数のリスト)
19.3.2 初期化関数のコールについて
OTTは、必要に応じてC初期化関数を生成します。初期化関数では、プログラムで使用されている各オブジェクト型について、どのバージョンの型が使用されているかを環境に通知します。INITFUNC
オプションでOTTを起動する場合は、初期化関数の名前を指定するか、初期化関数が含まれている実装ファイル(INITFILE
)の名前に基づいてデフォルト名を選択できます。
初期化関数には、環境ハンドル・ポインタとエラー・ハンドル・ポインタの2つの引数があります。一般的に、使用する初期化関数は1つですが、必ずしもそうである必要はありません。プログラムにコンパイル済の個別のピースがあり、異なる型を要求する場合は、各ピースに対して初期化関数が含まれた1つの初期化ファイルをそれぞれ要求して、OTTを個別に実行できます。
OCIEnvInit()
をコールするなど、明示的なOCIオブジェクト・コールによって環境ハンドルを作成した後に、環境ハンドルごとに初期化関数も明示的にコールする必要があります。これによって、各ハンドルからプログラム全体で使用されるすべてのデータ型にアクセスできます。
EXEC SQL CONTEXT USEやEXEC SQL CONNECTなどの埋込みSQL文を使用して環境ハンドルを暗黙的に作成する場合、ハンドルは暗黙的に初期化され、初期化関数をコールする必要はありません。これは、Pro*C/C++アプリケーションまたはPro*C/C++とOCIアプリケーションが併用される場合に適用されます。
次に、初期化関数の例を示します。
INTYPE
ファイルex2c.typを指定します。このファイルには次の型が含まれています。
TYPE SCOTT.PERSON TYPE SCOTT.ADDRESS
また、次のコマンドラインを含みます。
ott userid=scott/tiger intype=ex2c outtype=ex2co hfile=ex2ch.h initfile=ex2cv.c
OTTによって、次のようなファイルex2cv.cが生成されます。
#ifndef OCI_ORACLE #include <oci.h> #endif sword ex2cv(OCIEnv *env, OCIError *err) { sword status = OCITypeVTInit(env, err); if (status == OCI_SUCCESS) status = OCITypeVTInsert(env, err, "SCOTT", 5, "PERSON", 6, "$8.0", 4); if (status == OCI_SUCCESS) status = OCITypeVTInsert(env, err, "SCOTT", 5, "ADDRESS", 7, "$8.0", 4); return status; }
関数ex2cvによってタイプ・バージョン表が作成され、SCOTT.PERSON型およびSCOTT.ADDRESS型が挿入されます。
プログラムで明示的に環境ハンドルを作成する場合、明示的に作成するハンドルごとに初期化関数をコールする必要があるので、すべての初期化関数を生成し、コンパイルし、リンクしてください。プログラムが明示的に環境ハンドルを作成しない場合、初期化関数は必要ありません。
OTTで生成したヘッダー・ファイルを使用するプログラムでは、同時に生成された初期化関数も使用する必要があります。具体例として、コンパイルによってプログラムPにリンクされるコードが生成される場合を考えます。OTTによって生成されるヘッダー・ファイルをコンパイル環境にインクルードし、プログラムPのどこかで環境ハンドルが明示的に作成される場合は、それと同時にOTTによって生成される実装ファイルもコンパイルしてプログラムPにリンクする必要があります。この操作は、プログラマが正しく実行する必要があります。
19.3.3 初期化関数のタスク
C初期化関数は、OTTで処理する型のバージョン情報を提供します。C初期化関数は、OTTで処理する各オブジェクト・データ型の名前とバージョン識別子を型バージョン表に追加します。
Open Type Manager(OTM)では、特定のプログラムで使用する型のバージョンを識別するためにタイプ・バージョン表を使用します。OTTによって様々な初期化関数が別々に生成されると、タイプ・バージョン表に同じ型がいくつも追加されることがあります。型が何度も追加されると、そのたびにOTMによって同じバージョンの型が登録されているかどうかが確認されます。
初期化関数に対して関数プロトタイプを宣言し、その関数をコールするのは、OCIプログラマの役割です。
注意:
Oracleの現行のリリースでは、それぞれの型のバージョンは1つのみです。タイプ・バージョン表の初期化は、Oracleの将来のリリースとの互換性のためにのみ必要です。
19.4 Pro*C/C++アプリケーションでのOTTの使用について
Pro*C/C++アプリケーションの作成時の型の変換処理は、OCIベースのアプリケーションの作成時よりも簡単です。これは、プリコンパイラで生成されるコードによって自動的にタイプ・バージョン表が初期化されるためです。
Pro*C/C++アプリケーションでは、OTTによって生成されるC言語のヘッダー・ファイルを使用して、データベース・サーバーのオブジェクトにアクセスできます。このヘッダー・ファイルは、#include
文によりコードに組み込まれます。ヘッダー・ファイルをインクルードした後は、Pro*C/C++アプリケーションからホスト言語形式でオブジェクト・データにアクセスしたり、オブジェクト・データを操作したりできます。
図19-2は、Pro*C/C++でOTTを使用する場合に必要な手順を示しています。
-
SQLを使用してデータベースに型定義を作成します。
-
OTTで、オブジェクト型、REF型および名前付きコレクション型のC表現を含むヘッダー・ファイルを生成します。
INTYPE
パラメータとしてPro*C/C++に渡されるOUTTYPE
ファイルも生成されます。 -
ヘッダー・ファイルをPro*C/C++ソース・コード・ファイルにインクルードします。
-
Pro*C/C++アプリケーションをコンパイルし、Pro*C/C++のランタイム・ライブラリSQLLIBにリンクします。
-
Pro*C/C++実行可能ファイルをOracleサーバーで実行します。
前述の手順2が示すように、OTTによって生成されるOUTTYPE
ファイルは、Pro*C/C++プログラマにとって特別な用途があります。Pro*C/C++の起動時に、OUTTYPE
ファイルを新しいINTYPE
コマンドライン・パラメータに渡します。このファイルの内容は、OTT生成の構造体に対応付けるデータベース型を決定するためにプリコンパイラで使用されます。OCIでプログラミングしている場合は、バインド、定義および型情報へのアクセスのための特別な関数を使用して、この対応付けを明示的に行う必要があります。
また、プリコンパイラにより、OTTのOUTTYPE
(Pro*C/C++のINTYPE
)ファイルで名前が付けられた型を使用して、タイプ・バージョン表を初期化するコードが生成されます。
注意:
常にOTTからのOUTTYPE
ファイルをPro*C/C++のINTYPE
ファイルとして使用することをお薦めします。Pro*C/C++のINTYPE
ファイルを作成することも可能ですが、エラーが発生する可能性もあるためお薦めしません。
サーバーから取り出されたオブジェクトの属性を操作するには、OCIのデータ型のマッピングと操作のための関数をコールするのも1つの方法です。これを実行する前に、アプリケーションで、まずSQLEnvGet()
をコールしてOCI関数に渡すOCI環境ハンドルを取得し、次にSQLSvcCtxGet()
をコールしてOCI関数に渡すOCIサービス・コンテキストを取得する必要があります。Pro*C/C++には、オブジェクト属性の操作に使用できる機能もあります。
19.5 OTT参照
OTTの動作を制御するパラメータは、OTTコマンドラインでもCONFIGファイル内でも指定できます。また、一部のパラメータは、INTYPE
ファイルにも指定できます。この項では、次の項目について詳しく説明します。
この章では、次の規則を使用してOTTの構文を説明します。
-
イタリック文字列はユーザーが入力する内容です。
-
大文字の文字列は、そのとおりに入力する文字列です。ただし、大/小文字は区別されないため、小文字で入力しても有効です。
-
大カッコ[...]で囲んだ項目は、オプション項目です。
-
1つの項目(あるいはカッコで囲まれた複数の項目)の直後の省略記号(...)は、その項目を何度も繰り返し指定できることを示します。
-
これ以外の句読点記号は、示されているとおりに入力します。これには、'.'、'@'などが含まれます。
19.5.1 OTTコマンドライン構文
OTTコマンドライン・インタフェースは、OTTを明示的に起動してデータベース型をC構造体に変換するときに使用します。このインタフェースは、オブジェクトを活用するOCIアプリケーションまたはPro*C/C++アプリケーションの開発に必須です。
OTT
コマンドライン文は、キーワードOTTと、その後に続くOTTパラメータのリストによって構成されます。
OTTコマンドラインの文で指定できるパラメータは、次のとおりです。
[USERID=username/password[@db_name]] [INTYPE=in_filename] OUTTYPE=out_filename CODE={C|ANSI_C|KR_C} [HFILE=filename] [ERRTYPE=filename] [CONFIG=filename] [INITFILE=filename] [INITFUNC=filename] [CASE={SAME|LOWER|UPPER|OPPOSITE}] [SCHEMA_NAMES={ALWAYS|IF_NEEDED|FROM_INTYPE}] [TRANSITIVE=TRUE|FALSE]
注意:
通常、OTTコマンドの後に続くパラメータはどのような順序でもよく、常に必須となるのはOUTTYPE
およびCODE
パラメータのみです。
HFILE
パラメータは、ほとんどの場合に使用されます。省略すると、INTYPE
ファイルのそれぞれの型について、個別にHFILE
を指定する必要があります。OTTがINTYPE
ファイルで指定されていない型を変換する必要があると判断すると、エラーがレポートされます。したがって、INTYPE
ファイルが以前にOTT OUTTYPE
ファイルとして生成されている場合のみ、HFILE
パラメータを省略できます。
INTYPE
ファイルを省略すると、スキーマ全体が変換されます。詳細は、次の項のパラメータの説明を参照してください。
次にOTTコマンドライン文の例を示します(1行に入力します)。
OTT userid=scott/tiger intype=in.typ outtype=out.typ code=c hfile=demo.h errtype=demo.tls case=lower
OTTコマンドラインの各パラメータについて、この後の各項で説明します。
19.5.2 OTTパラメータ
OTTコマンドラインにパラメータを入力するときの書式は、次のとおりです。
parameter=value
parameterはリテラル・パラメータ文字列で、valueは有効なパラメータ設定値です。リテラル・パラメータ文字列は大/小文字を区別しません。
コマンドラインのパラメータは、空白またはタブのいずれかを使用して区切ります。
また、パラメータは構成ファイル内でも指定できます。ただし、この場合、行の中に空白を入れることはできないため、各パラメータは独立した行に指定する必要があります。さらに、パラメータCASE
、HFILE
、INITFUNC
およびINITFILE
は、INTYPE
ファイルに入れることができます。
19.5.2.1 USERID
USERIDパラメータでは、Oracleユーザー名およびパスワード、オプションのデータベース名(Oracle Netのデータベース指定文字列)を指定します。データベース名を省略すると、デフォルトのデータベースが使用されます。このパラメータの構文は、次のとおりです。
USERID=username/password[@db_name]
これが第1パラメータの場合は、「USERID=」を省略して、次のように指定できます。
OTT username/password...
USERIDパラメータはオプションです。省略した場合、OTTは自動的にユーザーCLUSTER$usernameでデフォルトのデータベースへの接続を試みます。usernameは、ユーザーのオペレーティング・システムのユーザー名です。
19.5.2.2 INTYPE
INTYPE
パラメータでは、オブジェクト型指定のリストの読取り元ファイルの名前を指定します。読み取ったリストにある型が、OTTによって変換されます。このパラメータの構文は、次のとおりです。
INTYPE=filename
USERIDが第1パラメータ、INTYPE
が第2パラメータで、USERID=を省略した場合は、INTYPE=
も省略できます。INTYPE
が指定されていない場合は、ユーザーのスキーマにおけるすべての型が変換されます。
OTT username/password filename...
INTYPE
ファイルは、型宣言に対するMakeファイルとみなすことができます。C構造体宣言の必要な型をリストします。
コマンドラインまたはINTYPE
ファイルのファイル名に拡張子が含まれていない場合は、「TYP」や「typ」などのプラットフォーム固有の拡張子が追加されます。
関連項目
19.5.2.3 OUTTYPE
OTTによって処理されるすべてのオブジェクト・データ型の型情報が書き込まれるファイルの名前を指定します。これには、INTYPE
ファイルで明示的に指定したすべての型が含まれます。さらに、変換対象である他の型の宣言で使用しているために変換された型が含まれる場合もあります(TRANSITIVE=TRUEの場合)。このファイルは、それ以後にOTTを起動するときにINTYPE
ファイルとして使用できます。
OUTTYPE=filename
INTYPE
パラメータとOUTTYPE
パラメータが同一のファイルを参照している場合、INTYPE
ファイルの古い情報は、新しいINTYPE
の情報に置き換えられます。これは、型の変更から始まり、型宣言の生成、ソースコードの編集、プリコンパイル、コンパイル、デバッグに至るサイクル内で、同一のINTYPE
ファイルを繰返し使用するときに便利です。
OUTTYPE
は必ず指定します。
コマンドラインまたはINTYPE
ファイルのファイル名に拡張子が含まれていない場合は、「TYP」や「typ」などのプラットフォーム固有の拡張子が追加されます。
19.5.2.4 CODE
CODE= C|KR_C|ANSI_C
OTTの出力を表すホスト言語です。CODE=C
、CODE=KR_C
またはCODE=ANSI_C
のいずれかを指定できます。「CODE=C
」は、「CODE=ANSI_C
」と等価です。
このパラメータは、デフォルト値がないので必ず指定する必要があります。
19.5.2.5 INITFILE
INITFILE
パラメータでは、OTTで生成した初期化ファイルを書き込むファイルの名前を指定します。このパラメータを省略すると、OTTは初期化関数を生成しません。
Pro*C/C++プログラムの場合、必要な初期化はSQLLIBランタイム・ライブラリによって実行されるため、INITFILE
は必要ありません。OCIプログラムのユーザーは、INITFILE
ファイルをコンパイルおよびリンクし、環境ハンドルの作成時に初期化関数をコールする必要があります。
コマンドラインまたはINTYPE
ファイルで指定したINITFILE
ファイル名に拡張子を付けなかった場合は、「C」または「.c」のようなプラットフォーム固有の拡張子が追加されます。
INITFILE=filename
19.5.2.6 INITFUNC
INITFUNC
パラメータは、OCIプログラムのみで使用します。OTTで生成する初期化関数の名前を指定します。このパラメータを省略すると、INITFILE
の名前から初期化関数の名前が付けられます。
INITFUNC=filename
19.5.2.7 HFILE
INTYPE
ファイルに記述した型の宣言でインクルード(.h)ファイルを指定しなかった場合に、OTTによって生成されるインクルード・ファイルの名前を指定します。INTYPE
ファイルで各型のインクルード・ファイルを個々に指定していない場合は、このパラメータが必要です。また、INTYPE
ファイルに記述していない型を、2つ以上の異なるファイルで宣言されている他の型で使用する場合(TRANSITIVE=TRUEの場合)は、INTYPEファイルに記述していない型も生成する必要があります。そのような場合もこのパラメータが必要です。
コマンドラインまたはINTYPE
ファイルで指定したHFILE
ファイル名に拡張子を付けなかった場合、「H」や「.h」のようなプラットフォーム固有の拡張子が追加されます。
HFILE=filename
19.5.2.8 CONFIG
CONFIGパラメータでは、共通に使用されるパラメータ指定を含むOTT構成ファイルの名前を指定します。また、パラメータ指定は、プラットフォームによって異なる位置にあるシステム構成ファイルから読み込まれます。残りのすべてのパラメータ指定は、コマンドラインまたはINTYPE
ファイルで指定する必要があります。
CONFIG=filename
注意: CONFIGパラメータは、CONFIGファイルでは使用できません。
19.5.2.9 ERRTYPE
このパラメータを指定すると、INTYPE
ファイルのリストが、すべての情報メッセージおよびエラー・メッセージとともにERRTYPEファイルに書き込まれます。情報メッセージおよびエラー・メッセージは、ERRTYPEを指定したかどうかに関係なく、標準出力に送信されます。
実質的に、ERRTYPEファイルはエラー・メッセージが追加されたINTYPE
ファイルのコピーです。ほとんどの場合、エラー・メッセージには、エラーの原因となったテキストへのポインタが含まれます。
コマンドラインまたはINTYPE
ファイルのERRTYPEファイル名に拡張子が付いていない場合は、「.TLS」または「.tls」など、プラットフォーム固有の拡張子が追加されます。
ERRTYPE=filename
19.5.2.10 CASE
このパラメータでは、OTT生成の特定のC言語の識別子を大文字で表記するか小文字で表記するかを指定します。CASE
の可能な値は、SAME
、LOWER
、UPPER
およびOPPOSITE
です。CASE = SAME
の場合は、データベース型と属性名をC識別子に変換するときに、大/小文字は変更されません。CASE=LOWER
の場合、大文字はすべて小文字に変換されます。CASE=UPPER
の場合、小文字はすべて大文字に変換されます。CASE=OPPOSITE
とすると、大文字はすべて小文字に変換され、小文字はすべて大文字に変換されます。
CASE=[SAME|LOWER|UPPER|OPPOSITE]
このパラメータは、INTYPE
ファイルに記述されていない識別子(明示的にリストされていない属性または型)のみに作用します。大/小文字の変換は、正当な識別子が生成された後で行われます。
注意:
INTYPE
で特定された型のC言語の構造体識別子の大/小文字の区別は、INTYPE
ファイルにおける大/小文字と同じです。たとえば、INTYPE
ファイルに次の行が含まれる場合、
TYPE Worker
OTTによって次のように生成されます。
struct Worker {...};
一方で、INTYPE
ファイルに次のように記述したとします。
TYPE wOrKeR
OTTによって次のように生成されます。
struct wOrKeR {...};
これはINTYPE
ファイルの大/小文字区別どおりです。
INTYPE
ファイルに記述されていない、大/小文字の区別のないSQL識別子は、CASE=SAME
の場合は大文字で、CASE=OPPOSITE
の場合は小文字で指定します。宣言時に引用符が付かなかったSQL識別子には、大/小文字の区別はありません。
19.5.2.11 SCHEMA_NAMES
このパラメータでは、デフォルトのスキーマからの型のデータベース名をOUTTYPE
ファイル内のスキーマ名で修飾する操作を制御できます。OTT生成のOUTTYPE
ファイルには、型の名前など、OTTの処理対象となる型の情報が含まれています。
関連項目
19.5.3 OTTパラメータの指定可能な場所
OTTのパラメータは、コマンドライン、コマンドラインで指定するCONFIGファイル内、またはその両方で指定します。パラメータの一部は、INTYPE
ファイルにも指定できます。
OTTは、次のように起動します。
OTT username/password parameters
コマンドラインのパラメータの1つが、
CONFIG=filename
の場合、構成ファイルfilenameからその他のパラメータが読み込まれます。
さらに、パラメータは、プラットフォームによって異なる位置にあるデフォルトの構成ファイルから読み込まれます。このファイルの存在は必要ですが、空でもかまいません。構成ファイルには、各パラメータを1行に1つずつ、空白を使用せずに入力する必要があります。
引数を指定しないでOTTを実行すると、オンラインのパラメータ参照が表示されます。
変換されるOTTの型は、INTYPE
パラメータで指定したファイルで命名されます。パラメータCASE
、INITFILE
、INITFUNC
およびHFILE
は、INTYPE
ファイルに入れることもできます。OTT生成のOUTTYPE
ファイルにはCASE
パラメータが含まれ、初期化ファイルが生成されている場合はINITFILE
およびINITFUNC
パラメータが含まれます。OUTTYPE
ファイルでは、型ごとにそれぞれHFILE
を指定します。
OTTコマンドの大/小文字区別は、プラットフォームによって異なります。
19.5.4 INTYPEファイルの構造
INTYPE
およびOUTTYPE
ファイルでは、OTTにより変換される型がリストされ、型または属性名の有効なC言語の識別子への変換方法を決定するときに必要なすべての情報が提供されます。これらのファイルには、1つ以上の型指定を記述します。また、次のオプションを指定する場合もあります。
-
CASE
-
HFILE
-
INITFILE
-
INITFUNC
CASE
、INITFILE
またはINITFUNC
オプションを指定する場合は、すべての型指定よりも前に指定する必要があります。これらのオプションをコマンドラインとINTYPE
ファイルの両方に指定した場合は、コマンドラインの値が使用されます。
単純なユーザー定義のINTYPE
ファイルと、そのファイルからOTTにより生成される完全なOUTTYPE
ファイルの例は、OTTでの型の継承のサポートを参照してください。
19.5.4.1 INTYPEファイルの型指定
INTYPE
での型指定によって、変換するオブジェクト・データ型の名前を指定します。次の記述は、ユーザー作成INTYPE
ファイルの例です。
TYPE employee TRANSLATE SALARY$ AS salary DEPTNO AS department TYPE ADDRESS TYPE PURCHASE_ORDER AS p_o
型指定の構造は、次のとおりです。
TYPE type_name [AS type_identifier] [VERSION [=] version_string] [HFILE [=] hfile_name] [TRANSLATE{member_name [AS identifier]}...]
type_nameの構文は、次のとおりです。
[schema_name.]type_name
この場合、schema_nameは、指定されたオブジェクト・データ型を所有するスキーマの名前で、type_nameはその型の名前です。デフォルト・スキーマは、OTTを実行するユーザーのスキーマです。デフォルト・データベースは、ローカル・データベースです。
型指定のコンポーネントは、次のとおりです。
-
type nameはオブジェクト・データ型の名前です。
-
type identifierは型を表すために使用されるC言語の識別子です。省略すると、デフォルトの名前マッピング・アルゴリズムが使用されます。
-
version stringは、OTTの以前の起動によってコードが生成されたときに使用された型のバージョン文字列です。バージョン文字列はOTTによって生成され、
OUTTYPE
ファイルに書き込まれます。このファイルは、後でOTTを実行するときにINTYPE
ファイルとして使用できます。バージョン文字列はOTTの操作には影響しませんが、最終的にこれを使用して、起動中のプログラムで使用されるオブジェクト型のバージョンが選択されます。 -
hfile nameは、該当する構造またはクラスの宣言が表れるヘッダー・ファイルの名前です。hfile nameを省略すると、宣言の生成時にはコマンドラインの
HFILE
パラメータで指定したファイルが使用されます。 -
member nameは、次のidentifierに変換される属性(データ・メンバー)の名前です。
-
identifierはユーザー・プログラムの属性を表すために使用されるC言語の識別子です。この方法によって、任意の数の属性に対して識別子を指定できます。指定していない属性については、デフォルトの名前マッピング・アルゴリズムが使用されます。
オブジェクト・データ型は、次のいずれかの場合に変換する必要があります。
-
INTYPE
ファイルに指定されている場合。 -
変換が必要な別の型を宣言する場合、およびTRANSITIVE=TRUEの場合は必須です。
明示的に記述していない型があり、その型が、正確に1つのファイルのみに宣言した型で必要だとします。この場合、明示的に記述していない型の変換結果は、それを必要とする明示的に宣言した型と同じファイルに書き込まれます。
明示的に記述していない型があり、その型が、複数の異なるファイルに宣言した型で必要だとします。この場合、要求された型の変換結果は、グローバルなHFILE
ファイルに書き込まれます。
関連項目
19.5.5 ネストした#includeファイル生成
OTTによって生成されるすべてのHFILE
で、他の必要なファイルが#includes
を使用してインクルードされ、そのファイルの名前から組み立てられた記号が#defines
を使用して定義されます。この記号は、
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 scott/tiger tott95i.typ outtype=tott95o.typ code=c
すると、次の2つのヘッダー・ファイルが生成されます。
ファイルtott95b.hは次のとおりです。
#ifndef TOTT95B_ORACLE #define TOTT95B_ORACLE #ifndef OCI_ORACLE #include <oci.h> #endif #ifndef TOTT95A_ORACLE #include "tott95a.h" #endif typedef OCIRef px3_ref; struct px3 { struct px1 col1; }; typedef struct px3 px3; struct px3_ind { OCIInd _atomic; struct px1_ind col1 }; typedef struct px3_ind px3_ind; #endif
ファイルtott95a.hは次のとおりです。
#ifndef TOTT95A_ORACLE #define TOTT95A_ORACLE #ifndef OCI_ORACLE #include <oci.h> #endif typedef OCIRef px1_ref; struct px1 { OCINumber col1; OCINumber col2; } typedef struct px1 px1; struct px1_ind { OCIInd _atomic; OCIInd col1; OCIInd col2; } typedef struct px1_ind px1_ind; #endif
このファイルでは、TOTT95B_ORACLEという記号を最初に定義しています。そのため、プログラマは、次の構造体を使用してtott95b.h
を条件付きでインクルードできます。その場合、tott95b.h
がインクルード・ファイルに依存しているかどうかを考慮する必要はありません。
#ifndef TOTT95B_ORACLE #include "tott95b.h" #endif
このテクニックを使用すると、「foo.h」などのファイルから「tott95b.h」をインクルードできます。この場合、「foo.h」からインクルードされる他のファイルに「tott95b.h」がインクルードされているかどうかを確認する必要はありません。
記号TOTT95B_ORACLEの定義の後に、ファイルoci.h
が#include
によってインクルードされます。OTT生成のすべてのHFILE
には、Pro*C/C++やOCIのプログラマに役立つ型と関数の宣言が含まれたoci.h
が組み込まれます。OTTが#include
にかぎ括弧を使用するのは、この場合のみです。
次に、ファイルtott95a.h
がインクルードされるのは、tott95a.h
に必要な「struct px1」の宣言が含まれているためです。INTYPE
ファイルにより型宣言の複数ファイルへの書込みが要求される場合は、OTTにより、その他の各HFILE
にインクルードする必要があるファイルが決定され、必要な#include
が生成されます。
この#include
では、OTTにより引用符が使用されるため注意してください。tott95b.h
がインクルードされたプログラムをコンパイルすると、tott95a.h
の検索はソース・プログラムの検出位置から開始され、それ以降は実装定義の検索規則に従って実行されます。この方法でtott95a.h
が検出されない場合は、INTYPE
ファイル内で完全ファイル名(/で始まるUNIXの絶対パス名など)を使用して、tott95a.h
の位置を指定する必要があります。
19.5.6 SCHEMA_NAMESの使用方法
このパラメータでは、OTTの接続先となるデフォルト・スキーマに含まれる型の名前を、OUTTYPE
ファイル内のスキーマ名で修飾するかどうかを指定します。
デフォルト・スキーマ以外のスキーマに基づく型の名前は、OUTTYPE
ファイル内のスキーマ名で常に修飾されます。
スキーマ名で修飾するかしないかで、プログラム実行中に型がどのスキーマで検索されるかが決定します。
次の3通りの設定があります。
-
SCHEMA_NAMES=ALWAYS(デフォルト)
OUTTYPE
ファイル内のすべての型名をスキーマ名で修飾します。 -
SCHEMA_NAMES=IF_NEEDED
デフォルト・スキーマに属する
OUTTYPE
ファイル内の型名はスキーマ名で修飾しません。デフォルト・スキーマ以外のスキーマに属する型名は、スキーマ名で修飾します。 -
SCHEMA_NAMES=FROM_INTYPE
INTYPE
ファイルに記述されている型は、INTYPE
ファイル内のスキーマ名で修飾されている場合にのみ、OUTTYPE
ファイル内のスキーマ名で修飾されます。デフォルト・スキーマ内の型は、INTYPE
ファイル内で記述されていなくても型の依存性によって生成する必要がある場合にはスキーマ名付きで記述されます。これは、その型に依存する型としてOTTで最初に検出された型がスキーマ名付きで記述されていた場合にのみ行われます。ただし、OTTが接続しているデフォルト・スキーマにない型は、常に、明示的に指定したスキーマ名付きで記述されます。
OTT生成のOUTTYPE
ファイルは、Pro*C/C++のINTYPE
ファイルになります。このファイルは、データベース型名をC言語の構造体名に対応付けます。この情報は、構造体内で正しいデータベース型が確実に選択されるようにするために、実行時に使用されます。OUTTYPE
ファイル(Pro*C/C++のINTYPE
ファイル)内のスキーマ名で型が指定される場合、その型はプログラムの実行中に名前付きスキーマ内で検索されます。型がスキーマ名なしで表示される場合、そのファイルはプログラムの接続先となるデフォルト・スキーマ内で検出されます。このデフォルト・スキーマは、OTTで使用されたデフォルト・スキーマと異なる場合があります。
例
SCHEMA_NAMES
にFROM_INTYPE
を設定し、INTYPE
ファイルで読み込みます。
TYPE Person TYPE joe.Dept TYPE sam.Company
OTTで生成した構造体を使用して、Pro*C/C++アプリケーションでsam.Company、joe.DeptおよびPersonの各型を使用します。Personにはスキーマ名が付いていないので、アプリケーションが接続されているスキーマ内のPerson型を参照します。
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 or TYPE joe.Person
joe.Address型が指定されていない場合は、joe.Person型にネストされたオブジェクト型として使用されます。TYPE joe.PersonがINTYPE
ファイルに記述されている場合は、OUTTYPE
ファイルにはTYPE joe.PersonとTYPE joe.Addressが表示されます。INTYPE
ファイルにType Personが記述されている場合は、TYPE PersonおよびTYPE AddressがOUTTYPE
ファイルに表示されます。
joe.Address型がOTTによって変換された複数の型に埋め込まれていた場合にも、INTYPE
ファイル内で明示的に指定されていなければ、埋め込まれたjoe.Address型が最初に検出されたときに、スキーマ名を使用するかどうかが決定されます。なんらかの理由で、joe.Address型にはスキーマ名を付け、Person型にはスキーマ名を付けない場合は、次のように明示的に要求する必要があります。
TYPE joe.Address
これはINTYPE
FILEで要求します。
各型を単一のスキーマ内で宣言する通常の場合は、すべての型名をINTYPE
ファイル内のスキーマ名で修飾することが最も安全です。
19.5.7 デフォルト名のマッピング
OTTでオブジェクト型または属性のC識別子名を作成する場合、OTTは、その名前をデータベース・キャラクタ・セットから有効なC識別子に変換します。最初に、名前はデータベース・キャラクタ・セットからOTTで使用するキャラクタ・セットに変換されます。次に、変換した結果の名前がINTYPE
ファイルに指定されている場合は、その変換内容が使用されます。それ以外の場合、名前はCASE
オプションで指定したコンパイラのキャラクタ・セットに1文字ずつOTTにより変換されます。この詳細を次に説明します。
OTTによってデータベース・エンティティ名が読み込まれると、データベース・キャラクタ・セットからOTTで使用するキャラクタ・セットに自動的に変換されます。OTTがデータベース・エンティティ名を正常に読み込むには、その名前のすべての文字がOTTのキャラクタ・セット内で検出される必要はあります。しかし、文字によっては2つのキャラクタ・セット間でエンコーディングが異なる場合があります。
必要な文字がOTTで使用するキャラクタ・セットにすべて含まれていることを保証するには、データベース・キャラクタ・セットと同じものを使用するのが最も簡単な方法です。ただし、OTTのキャラクタ・セットは、コンパイラのキャラクタ・セットのスーパーセットである必要があります。つまり、コンパイラのキャラクタ・セットが7ビットASCIIの場合、OTTのキャラクタ・セットはサブセットとして7ビットASCIIを含む必要があります。コンパイラのキャラクタ・セットが7ビットEBCDICの場合は、OTTのキャラクタ・セットはサブセットとして7ビットEBCDICを含む必要があります。OTTで使用されるキャラクタ・セットを指定するには、環境変数NLS_LANGを設定する方法と、プラットフォーム固有の他のメカニズムを使用する方法があります。
OTTがデータベース・エンティティの名前を読み取ると、その名前は、OTTで使用するキャラクタ・セットからコンパイラのキャラクタ・セットに変換されます。名前の変換がINTYPE
ファイルで指定されている場合は、OTTはその変換を使用します。
それ以外の場合、OTTは名前を次のように変換します。
-
最初に、OTTのキャラクタ・セットがマルチバイト・キャラクタ・セットの場合、その名前にある、等価のシングルバイト文字を持つマルチバイト文字は、シングルバイト文字に変換されます。
-
次に、その名前は、OTTのキャラクタ・セットからコンパイラのキャラクタ・セットに変換されます。コンパイラのキャラクタ・セットは、US7ASCIIのように、シングルバイト・キャラクタ・セットです。
-
最後に、有効になっている
CASE
オプションに従って、文字の大/小文字が設定されます。そして、C言語の識別子で無効な文字、またはコンパイラのキャラクタ・セットに変換内容がない文字は、アンダースコアに置き換えられます。1文字でもアンダースコアに置き換えられると、OTTから警告メッセージが表示されます。名前に含まれる文字がすべてアンダースコアに置き換えられると、OTTによってエラー・メッセージが表示されます。
文字単位の名前の変換では、コンパイラのキャラクタ・セットにあるアンダースコア、数字またはシングルバイト文字は変更されません。したがって、有効なC言語の識別子は変更されません。
名前の変換ではたとえば、ウムラウトの付いた「o」、アクセント符号の付いた「a」などのシングルバイト文字をそれぞれ「o」や「a」に変換したり、またマルチバイト文字をシングルバイトと等価に変換できます。名前に等価のシングルバイトがないマルチバイト文字がある場合、通常、その名前の変換はエラーとなります。この場合、ユーザーは、INTYPE
ファイルで名前の変換を指定する必要があります。
OTTでは、同じC言語の名前に複数のデータベース識別子がマップされたために発生する名前の重複は検出されません。また、データベース識別子がC言語のキーワードにマップされる場合に発生する命名の問題も検出されません。
19.5.8 制限事項
OTTを使用する場合は、次の制限が適用されます。
19.5.8.1 ファイル名比較
現在、OTTでは、2つのファイルが同じかどうかは、コマンドラインまたはINTYPE
ファイルでユーザーが指定したファイル名を比較して判断しています。OTTで2つのファイル名が同一のファイルを参照しているかどうかを判別する必要がある場合は、1つの潜在的な問題が生じます。たとえば、OTT生成のファイルfoo.hに、foo1.hに書き込まれた型の宣言と、/private/smith/foo1.hに書き込まれた別の型の宣言が必要な場合、OTTは2つのファイルが同じであれば#include
を1つ、異なっていれば#include
を2つ生成する必要があります。ただし、実際には、OTTでは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
は重複して記述されます。
そのため、コマンドラインまたはINTYPE
ファイルでファイルを複数回記述するときは、各記述で正確に同じファイル名を使用する必要があります。