ヘッダーをスキップ
Pro*C/C++プログラマーズ・ガイド
11g リリース1(11.1)
E05689-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

19 Object Type Translator(OTT)

この章では、Pro*C/C++アプリケーションで使用するためにデータベース・オブジェクト・タイプ、LOB型およびコレクション型をC言語の構造体にマップする、Object Type Translator(OTT)について説明します。

この章の項目は、次のとおりです。

OTT概要

OTT(Object Type Translator)は、Oracleサーバーのユーザー定義型を利用するアプリケーションの開発に役立ちます。

SQL CREATE TYPE文を使用して、オブジェクト型を作成できます。これらの型の定義をデータベースに格納し、データベースの表を作成するときに使用できます。これらの表への移入後は、OCI、Pro*C/C++またはJavaのプログラマは表に格納されているオブジェクトにアクセスできます。

オブジェクト・データにアクセスするアプリケーションには、データをホスト言語形式で表す機能が必要です。これは、オブジェクト型をC言語の構造体として表現することで実現できます。プログラマがデータベース・オブジェクト・タイプを表す構造体宣言を、手入力でコーディングすることは可能です。ただし、多くの型がある場合、この作業は時間がかかり、エラーを生む原因になりがちです。OTTを使用すると、必要な構造体の宣言が自動的に生成されるため、作業を軽減できます。Pro*C/C++の場合、アプリケーション側では、OTTによって生成されたヘッダー・ファイルをインクルードするのみで済みます。OCIの場合は、アプリケーション側ではOTTによって生成される初期化関数もコールする必要があります。

OTTは、格納されているデータ型を表す構造体を作成するのみでなく、オブジェクト型またはそのフィールドがNULLかどうかを示す対になるインジケータ構造体も生成します。

オブジェクト型の詳細は、第16章「LOB」第17章「オブジェクト」および第18章「コレクション」を参照してください。

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;

構造体宣言で使用されるデータ型(OCIStringOCIIndなど)はOracle8の新しい特殊データ型です。これらの型の詳細は、「OTTデータ型のマッピング」を参照してください。

これ以降の項では、OTTの使用について次の事柄を説明します。

次の各項では、OTTをOCIおよびPro*C/C++とともに使用する方法について説明してから、参考のためにコマンドライン構文、パラメータ、INTYPEファイルの構造、ネストされた#includeファイルの生成、スキーマ名の使用方法、デフォルト名のマッピングおよび制限事項について説明します。

データベースにおける型の作成

OTTを使用するには、最初にオブジェクト型または名前付きコレクション型を作成して、データベースに格納します。そのためには、SQL CREATE TYPE文を使用します。

関連項目: オブジェクト型およびコレクション型の作成方法の詳細は、第17章「オブジェクト」を参照してください。

OTTの起動

次の手順は、OTTを起動することです。

OTTのパラメータは、コマンドラインまたは構成ファイル内で指定できます。一部のパラメータはINTYPEファイルでも指定できます。

パラメータを数箇所で指定すると、優先順位が最も高いのはコマンドラインで指定した値で、次にINTYPEファイル内の値、ユーザー定義の構成ファイルの値、デフォルトの構成ファイル内の値の順になります。

グローバル・オプション、つまりコマンドラインのオプションまたはINTYPEファイルのTYPE文の前のオプションについては、コマンドラインの値によりINTYPEファイルの値が上書きされます。(INTYPEファイルでグローバルとして指定できるオプションには、CASECODEINITFILEOUTDIRおよびINITFUNCがあります。HFILEは含まれません。)TYPEを指定するINTYPEファイルのオプションは、特定の型にのみ適用されます。その型に適用される、コマンドラインで指定したそれ以外のオプションは上書きされます。TYPE person HFILE=p.hと入力した場合、オプションはpersonにのみ適用され、コマンドラインのHFILEは上書きされます。文はコマンドライン・パラメータとはみなされません。

コマンドライン

コマンドラインに設定されたパラメータ(オプションとも呼ばれます)は、他で設定されたパラメータを上書きします。

関連項目: オブジェクト型およびコレクション型の作成方法の詳細は、第17章「オブジェクト」を参照してください。

構成ファイル

構成ファイルは、OTTパラメータが入っているテキスト・ファイルです。ファイル内の非空白行には、1つのパラメータと、それに対応付けられた1つ以上の値が入っています。1行に2つ以上のパラメータを指定した場合は、最初のパラメータのみが使用されます。構成ファイルの非空白行では、空白は使用できません。

構成ファイル名は、コマンドラインで指定できます。さらに、デフォルトの構成ファイルは常に読み込まれます。このデフォルトの構成ファイルは、常に存在する必要がありますが、空でもかまいません。デフォルトの構成ファイルの名前はottcfg.cfgで、構成ファイルの位置はシステム固有です。詳細は、プラットフォーム固有のマニュアルを参照してください。

INTYPEファイル

INTYPEファイルは、OTTにより変換される型のリストを示します。

パラメータCASEHFILEINITFUNCおよびINITFILEは、INTYPEファイルに入れることができます。詳細は、「INTYPEファイル」を参照してください。

OTTコマンドライン

ほとんどのプラットフォームでは、OTTはコマンドラインから起動します。入力ファイル、出力ファイルおよびデータベース接続情報などを指定できます。プラットフォームでOTTを起動する方法は、プラットフォーム固有のマニュアルで確認してください。

次の例(例1)は、コマンドラインからOTTを起動する方法を示しています。

ott userid=scott/tiger intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h

注意:

等号(=)の前後には空白は入力できません。

次の各項では、この例で使用しているコマンドラインの要素を説明します。

OTTコマンドラインの様々なオプションの詳細は、「OTT参照」を参照してください。

OTT

OTTを起動します。必ずコマンドラインの先頭に置きます。

Userid

OTTで使用されるデータベース接続情報を指定します。例1では、OTTはユーザー名scottおよびパスワードtigerを使用して接続しようとします。

INTYPE

使用するINTYPEファイルの名前を指定します。例1では、INTYPEファイルの名前をdemoin.typと指定しています。

OUTTYPE

OUTTYPEファイル名を指定します。OTTは、C言語のヘッダー・ファイルを生成するときに、変換対象の型の情報をOUTTYPEファイルにも書き込みます。このファイルには、変換対象の型ごとに、バージョン文字列と、そのC言語での表現が書き込まれたヘッダー・ファイルが記録されます。

例1では、OUTTYPEファイルの名前をdemoout.typと指定しています。


注意:

INITFILEで既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。

CODE

変換のターゲット言語を指定します。次のオプションがあります。

  • C(ANSI_Cと等価)

  • ANSI_C(ANSI C対応)

  • KR_C(Kernighan & Ritchie C対応)

現在、デフォルト値はないため、このパラメータは必須です。

構造体宣言はC言語の両言語で同一です。INITFILEファイルで定義された初期化関数が定義されるスタイルは、KR_Cが使用されるかどうかによって決まります。INITFILEオプションを使用しない場合は、3つのオプションはすべて同じです。

HFILE

生成された構造体を書き込むCヘッダー・ファイルの名前を指定します。例1では、生成された構造体はファイルdemo.hに格納されます。


注意:

HFILEで既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。

INITFILE

型初期化関数を書き込むCソース・ファイルの使用を指定します。

初期化関数は、OCIプログラム内でのみ必要です。Pro*C/C++プログラムでは、Pro*C/C++ランタイム・ライブラリによって型が自動的に初期化されます。


注意:

INITFILEで既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルには実際に書き込みません。これにより、ファイルの変更時間を節約でき、UNIXのMakeおよび他のプラットフォームでの類似機能で、不必要な再コンパイルが実行されません。

INITFUNC

INITFILEに定義する初期化関数の名前を指定します。

このパラメータを使用せずに初期化関数を生成すると、初期化関数の名前は、INITFILEの基本名と同一になります。

この関数は、OCIプログラム内でのみ必要です。

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およびADDRESSは、C言語の構造体では常にそれぞれemployeeおよびADDRESSとなります。これらの構造体のメンバーは、小文字で名前が付けられます。

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型の属性を持っている場合、ADDRESSはPerson型の定義に必要なため変換されます。


注意:

TRANSITIVE = FALSEを指定して、INTYPEファイルに指定されていない型が生成されないように指定できます。デフォルトでは、TRANSITIVEはTRUEに設定されます。

通常の大/小文字の区別がないSQL識別子は、INTYPEファイルで、大/小文字のどのような組合せのつづりでもかまいません。そして、引用符は付けません。

TYPE "Person"などの引用符を使用すると、大/小文字を区別して作成されたCREATE TYPE "Person"などのSQL識別子が参照されます。宣言されたときに引用符が付けられたSQL識別子では、大/小文字が区別されます。

また、引用符は、TYPE "CASE"のようにOTT予約語であるSQL識別子を参照するためにも使用できます。この場合、そのSQL識別子がCREATE TYPE Caseのように大/小文字を区別しないで作成されていれば、名前に引用符を付けるときは、その名前を大文字にする必要があります。SQL識別子名を参照するために使用するOTT予約語に引用符を付けなければ、INTYPEファイル内で構文エラーがレポートされます。

関連項目: INTYPEファイル構造の仕様の詳細と使用可能なオプションは、「INTYPEファイルの構造」を参照してください。

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インジケータ構造体」を参照してください。

構造体宣言のデータ型OCIStringOCINumberOCIDateOCIIndはOracle8の新しいオブジェクト型のCマッピングです。オブジェクト型属性のデータ型をマップするためにここで使用されます。たとえば、empno属性のNUMBERデータ型は、新しいOCINumberデータ型にマップします。また、これらの新しいデータ型は、バインド変数および定義変数の型としても使用します。

関連項目: OCIアプリケーションのオブジェクト・データ型を含むデータ型の使用方法の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。

オブジェクト・データ型のC言語へのマッピング

この項では、オブジェクトの属性型を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型マッピングの例

次の例は、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_typeがありますが、構造体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;
   ...
}

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の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』のオブジェクト型の説明を参照してください。

OTTでの型の継承のサポート

オブジェクトの型の継承をサポートするために、OTTでは、カプセル化された構造体内で継承される属性を特別な名前'_super'で宣言してから新規属性を宣言することで、オブジェクト・サブタイプを表すC言語の構造体が生成されます。したがって、スーパータイプから継承されるオブジェクト・サブタイプの場合、構造体の最初の要素の名前は、'_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_tStudent_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ファイル

OUTTYPEファイルは、OTTコマンドラインで名前が付けられます。OTTは、C言語のヘッダー・ファイルを生成するときに、変換結果をOUTTYPEファイルにも書き込みます。このファイルには、変換対象の型ごとに、バージョン文字列と、そのC言語での表現が書き込まれたヘッダー・ファイルが記録されます。

OTTを1度実行して生成した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ファイルにPERSONADDRESSの両方のエントリがあるとします。person型を完全に変換するには、最初にaddressを変換する必要があります。

パラメータTRANSITIVEをTRUE(デフォルト)に設定していると、OTTでは、変換の実行前に、INTYPEファイル内の型相互の依存性が分析され、必要であれば他の型も変換されます。

OCIアプリケーションでのOTTの使用

OTTによって生成されるC言語のヘッダー・ファイルと実装ファイルは、データベース・サーバーのオブジェクトにアクセスするOCIアプリケーションで使用できます。ヘッダー・ファイルをOCIコードに取込むには、#include文を使用します。

OCIアプリケーションでは、ヘッダー・ファイルをインクルードした後に、ホスト言語形式のオブジェクト・データにアクセスして操作できます。

図19-1は、OCIでOTTを使用する場合に必要な手順を示しています。

  1. SQLを使用してデータベースに型定義を作成します。

  2. OTTを使用して、C言語での表現によるオブジェクト型と名前付きコレクション型を含むヘッダー・ファイルを生成します。また、INITFILEオプションを使用して名前が付けられた実装ファイルも生成します。

  3. アプリケーションを記述します。OCIアプリケーションでユーザーが記述したコードで、INITFUNC関数を宣言してコールします。

  4. ヘッダー・ファイルをOCIソース・コード・ファイルにインクルードします。

  5. OCIアプリケーションをOTT生成の実装ファイルとともにコンパイルしてOCIライブラリにリンクします。

  6. OCI実行可能ファイルをOracleサーバーに対して実行します。

図19-1 OCIでのOTTの使用方法

OCIでのOTTの使用方法
「図19-1 OCIでのOTTの使用方法」の説明

OCIによるオブジェクトのアクセスと操作

アプリケーション内では、OTTによって生成されたヘッダー・ファイルに表示される型を持つように宣言されたプログラム変数を使用すると、OCIプログラムでバインド操作と定義操作を実行できます。

たとえば、アプリケーションで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章(データ型のマップと操作の関数のリスト)

初期化関数のコール

OTTでは、必要に応じてC言語の初期化関数が生成されます。初期化関数では、プログラムで使用されている各オブジェクト型について、どのバージョンの型が使用されているかを環境に通知します。初期化関数名は、OTTの起動時にINITFUNCオプションを使用して指定できます。また、その関数を含む実装ファイル(INITFILE)の名前に基づいて、OTTでデフォルト名を選択することもできます。

初期化関数には、環境ハンドル・ポインタとエラー・ハンドル・ポインタの2つの引数があります。一般的に、使用する初期化関数は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にリンクする必要があります。この操作は、プログラマが正しく実行する必要があります。

初期化関数のタスク

C言語の初期化関数は、OTTで処理される型のバージョン情報を提供します。また、OTTで処理する各オブジェクト・データ型の名前とバージョン識別子をタイプ・バージョン表に追加します。

Open Type Manager(OTM)では、特定のプログラムで使用する型のバージョンを識別するためにタイプ・バージョン表を使用します。OTTによって様々な初期化関数が別々に生成されると、タイプ・バージョン表に同じ型がいくつも追加されることがあります。型が何度も追加されると、そのたびにOTMによって同じバージョンの型が登録されているかどうかが確認されます。

初期化関数の関数プロトタイプの宣言と関数のコールは、OCIのプログラマが行います。


注意:

Oracle9iの現行のリリースでは、それぞれの型のバージョンは1つのみです。タイプ・バージョン表の初期化は、Oracle9iの将来のリリースとの互換性のためにのみ必要です。

Pro*C/C++アプリケーションでのOTTの使用

Pro*C/C++アプリケーションの作成時の型の変換処理は、OCIベースのアプリケーションの作成時よりも簡単です。これは、プリコンパイラで生成されるコードによって自動的にタイプ・バージョン表が初期化されるためです。

Pro*C/C++アプリケーションでは、OTTによって生成されるC言語のヘッダー・ファイルを使用して、データベース・サーバーのオブジェクトにアクセスできます。このヘッダー・ファイルは、#include文によりコードに組み込まれます。ヘッダー・ファイルをインクルードした後は、Pro*C/C++アプリケーションからホスト言語形式でオブジェクト・データにアクセスしたり、オブジェクト・データを操作したりできます。

図19-2は、Pro*C/C++でOTTを使用する場合に必要な手順を示しています。

  1. SQLを使用してデータベースに型定義を作成します。

  2. OTTを使用して、C言語での表現によるオブジェクト型、REF型および名前付きコレクション型を含むヘッダー・ファイルを生成します。INTYPEパラメータとしてPro*C/C++に渡されるOUTTYPEファイルも生成されます。

  3. ヘッダー・ファイルをPro*C/C++ソース・コード・ファイルにインクルードします。

  4. Pro*C/C++アプリケーションをコンパイルし、Pro*C/C++のランタイム・ライブラリSQLLIBにリンクします。

  5. Pro*C/C++実行可能ファイルをOracleサーバーで実行します。

図19-2 オブジェクト指向Pro*C/C++アプリケーションの作成

オブジェクト指向Pro*C/C++アプリケーションの作成
「図19-2 オブジェクト指向Pro*C/C++アプリケーションの作成」の説明

前述の手順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++には、オブジェクト属性の操作に使用できる機能もあります。詳細は、第17章「オブジェクト」を参照してください。

Pro*C/C++からOCI関数をコールするプロセスの概要は、「OCIによるオブジェクトのアクセスと操作」の項を、詳細は『Oracle Call Interfaceプログラマーズ・ガイド』の第8章を参照してください。

OTT参照

OTTの動作を制御するパラメータは、OTTコマンドラインでもCONFIGファイル内でも指定できます。また、一部のパラメータは、INTYPEファイルにも指定できます。この項では、次の項目について詳しく説明します。

この章では、次の規則を使用してOTTの構文を説明します。

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ファイルで指定されていない型を変換する必要があると判断すると、エラーがレポートされます。したがって、HFILEパラメータを省略できるのは、INTYPEファイルが以前にOTTのOUTTYPEファイルとして生成された場合のみです。

INTYPEファイルを省略すると、スキーマ全体が変換されます。詳細は、この次の項にあるパラメータの説明を参照してください。

次にOTTコマンドライン文の例を示します(1行に入力します)。

OTT userid=scott/tiger intype=in.typ outtype=out.typ code=c hfile=demo.h errtype=demo.tls case=lower

OTTコマンドラインの各パラメータについて、この後の各項で説明します。

OTTパラメータ

OTTコマンドラインにパラメータを入力するときの書式は、次のとおりです。

parameter=value

parameterはリテラル・パラメータ文字列で、valueは有効なパラメータ設定値です。リテラル・パラメータ文字列は大/小文字を区別しません。

コマンドラインのパラメータは、空白またはタブのいずれかを使用して区切ります。

また、パラメータは構成ファイル内でも指定できます。ただし、この場合、行の中に空白を入れることはできないため、各パラメータは独立した行に指定する必要があります。さらに、パラメータCASEHFILEINITFUNCおよびINITFILEINTYPEファイルに入れることができます。

USERID

USERIDパラメータでは、Oracleユーザー名およびパスワード、オプションのデータベース名(Oracle Netのデータベース指定文字列)を指定します。データベース名を省略すると、デフォルトのデータベースが想定されます。このパラメータの構文は、次のとおりです。

USERID=username/password[@db_name]

これが第1パラメータの場合は、「USERID=」を省略して、次のように指定できます。

OTT username/password...

USERIDパラメータはオプションです。省略した場合、OTTは自動的にユーザーCLUSTER$usernameでデフォルトのデータベースへの接続を試みます。usernameは、ユーザーのオペレーティング・システムのユーザー名です。

INTYPE

INTYPEパラメータでは、オブジェクト型指定のリストを読み込む元のファイルの名前を指定します。OTTは、このリストに含まれる型を1つずつ変換します。このパラメータの構文は、次のとおりです。

INTYPE=filename

USERIDが第1パラメータ、INTYPEが第2パラメータで、USERID=を省略した場合は、INTYPE=も省略できます。INTYPEが指定されていない場合は、ユーザーのスキーマにおけるすべての型が変換されます。

OTT username/password filename...

INTYPEファイルは、型宣言のMakeファイルと考えることができます。C言語の構造体宣言の必要な型をINTYPEファイルにリストします。INTYPEファイルの形式は、「INTYPEファイルの構造」を参照してください。

コマンドラインまたはINTYPEファイルのファイル名に拡張子が含まれていない場合は、「TYP」や「typ」などのプラットフォーム固有の拡張子が追加されます。

OUTTYPE

OTTによって処理されるすべてのオブジェクト・データ型の型情報が書き込まれるファイルの名前を指定します。OUTTYPEファイルには、INTYPEファイルで明示的に指定したすべての型が含まれます。さらに、変換対象である他の型の宣言で使用しているために変換された(TRANSITIVE=TRUEの場合)型が含まれる場合もあります。このファイルは、それ以後にOTTを起動するときにINTYPEファイルとして使用できます。

OUTTYPE=filename

INTYPEパラメータとOUTTYPEパラメータが同一のファイルを参照している場合、INTYPEファイルの古い情報は、新しいINTYPEの情報に置き換えられます。このことは、型の変更から型宣言の生成、ソース・コードの編集、プリコンパイル、コンパイル、デバッグまでのサイクルで、同一のINTYPEファイルを繰返し使用するときに便利です。

OUTTYPEは必ず指定します。

コマンドラインまたはINTYPEファイルのファイル名に拡張子が含まれていない場合は、「TYP」や「typ」などのプラットフォーム固有の拡張子が追加されます。

CODE

CODE= C|KR_C|ANSI_C

OTTの出力を表すホスト言語を指定します。この場合、CODE=CCODE=KR_CCODE=ANSI_Cのいずれかを指定できます。CODE=Cは、CODE=ANSI_Cと等価です。

このパラメータは、デフォルト値がないため必ず指定する必要があります。

INITFILE

INITFILEパラメータでは、OTTで生成した初期化ファイルを書き込むファイルの名前を指定します。このパラメータを省略すると、初期化関数は生成されません。

Pro*C/C++プログラムの場合、必要な初期化はSQLLIBランタイム・ライブラリによって実行されるため、INITFILEは必要ありません。OCIプログラムのユーザーは、INITFILEファイルをコンパイルおよびリンクし、環境ハンドルの作成時に初期化関数をコールする必要があります。

コマンドラインまたはINTYPEファイルで指定したINITFILEファイル名に拡張子を付けなかった場合は、「C」または「.c」のようなプラットフォーム固有の拡張子が追加されます。

INITFILE=filename

INITFUNC

INITFUNCパラメータが使用されるのは、OCIプログラムの場合のみです。このパラメータでは、OTT生成の初期化関数の名前を指定します。このパラメータを省略すると、INITFILEの名前から初期化関数の名前が付けられます。

INITFUNC=filename

HFILE

INTYPEファイルに記述した型の宣言でインクルード(.h)ファイルを指定しなかった場合に、OTTによって生成されるインクルード・ファイルの名前を指定します。INTYPEファイルで各型のインクルード・ファイルを個々に指定していない場合は、このパラメータが必要です。INTYPEファイルに記述していない型を、2つ以上の異なるファイルで宣言した他の型で使用する場合(TRANSITIVE=TRUEの場合)は、INTYPEファイルに記述していない型も生成する必要があります。そのような場合もこのパラメータが必要です。

コマンドラインまたはINTYPEファイルで指定したHFILEファイル名に拡張子を付けなかった場合、「H」や「.h」のようなプラットフォーム固有の拡張子が追加されます。

HFILE=filename

CONFIG

CONFIGパラメータでは、共通に使用されるパラメータ指定を含むOTT構成ファイルの名前を指定します。また、パラメータ指定は、プラットフォームによって異なる位置にあるシステム構成ファイルから読み込まれます。残りのすべてのパラメータ指定は、コマンドラインまたはINTYPEファイルで指定する必要があります。

CONFIG=filename

注意: CONFIGパラメータは、CONFIGファイルでは使用できません。

ERRTYPE

このパラメータを指定すると、INTYPEファイルのリストが、すべての情報メッセージおよびエラー・メッセージとともにERRTYPEファイルに書き込まれます。情報メッセージおよびエラー・メッセージは、ERRTYPEを指定したかどうかに関係なく、標準出力に送信されます。

実質的に、ERRTYPEファイルはエラー・メッセージが追加されたINTYPEファイルのコピーです。ほとんどの場合、エラー・メッセージには、エラーの原因となったテキストへのポインタが含まれます。

コマンドラインまたはINTYPEファイルのERRTYPEファイル名に拡張子が付いていない場合は、「.TLS」または「.tls」など、プラットフォーム固有の拡張子が追加されます。

ERRTYPE=filename

CASE

このパラメータでは、OTT生成の特定のC言語の識別子を大文字で表記するか小文字で表記するかを指定します。CASEの可能な値は、SAMELOWERUPPERおよび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識別子には、大/小文字の区別はありません。

SCHEMA_NAMES

このパラメータでは、デフォルトのスキーマからの型のデータベース名をOUTTYPEファイル内のスキーマ名で修飾する操作を制御できます。OTT生成のOUTTYPEファイルには、型の名前など、OTTの処理対象となる型の情報が含まれています。

詳細は、「SCHEMA_NAMESの使用方法」を参照してください。

TRANSITIVE

値TRUE(デフォルト)またはFALSEをとります。INTYPEファイルに明示的に指定されていない型の依存性が変換されるかどうかを示します。TRANSITIVE=FALSEを指定すると、INTYPEファイルに指定されていない型は生成されません。これは、他に生成される型の属性の型として使用される場合も同じです。

OTTパラメータの使用場所

OTTのパラメータは、コマンドライン、コマンドラインで指定するCONFIGファイル内、またはその両方で指定します。パラメータの一部は、INTYPEファイルでも指定できます。

OTTを起動するには、次のように入力します。

OTT username/password parameters

コマンドラインのパラメータの1つが、

CONFIG=filename

の場合、構成ファイルfilenameからその他のパラメータが読み込まれます。

さらに、パラメータは、プラットフォームによって異なる位置にあるデフォルトの構成ファイルから読み込まれます。このファイルは、常に存在する必要がありますが、空でもかまいません。構成ファイルには、各パラメータを1行に1つずつ、空白を使用せずに入力する必要があります。

引数を指定しないでOTTを実行すると、オンラインのパラメータ参照が表示されます。

OTTの変換対象の型は、INTYPEパラメータで指定されるファイルにおいて名前が指定されます。パラメータCASEINITFILEINITFUNCおよびHFILEは、INTYPEファイルに入れることもできます。OTT生成のOUTTYPEファイルにはCASEパラメータが含まれ、初期化ファイルが生成されている場合はINITFILEおよびINITFUNCパラメータが含まれます。OUTTYPEファイルでは、型ごとにそれぞれHFILEを指定します。

OTTコマンドの大/小文字区別は、プラットフォームによって異なります。

INTYPEファイルの構造

INTYPEおよびOUTTYPEファイルでは、OTTにより変換される型がリストされ、型または属性名の有効なC言語の識別子への変換方法を決定するときに必要なすべての情報が提供されます。これらのファイルには、1つ以上の型指定を記述します。また、次のオプションを指定する場合もあります。

  • CASE

  • HFILE

  • INITFILE

  • INITFUNC

CASEINITFILEまたはINITFUNCオプションを指定する場合は、すべての型指定よりも前に指定する必要があります。これらのオプションをコマンドラインとINTYPEファイルの両方に指定した場合は、コマンドラインの値が使用されます。

単純なユーザー定義のINTYPEファイルと、そのファイルからOTTにより生成される完全なOUTTYPEファイルの例は、「OTTでの型の継承のサポート」を参照してください。

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ファイルに書き込まれます。

ネストした#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では引用符が使用されるため注意してください。tott95b.hがインクルードされたプログラムをコンパイルすると、tott95a.hの検索はソース・プログラムの検出位置から開始され、それ以降は実装定義の検索規則に従って実行されます。この方法でtott95a.hが検出されない場合は、INTYPEファイル内で完全ファイル名(/で始まるUNIXの絶対パス名など)を使用して、tott95a.hの位置を指定する必要があります。

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_NAMESFROM_INTYPEを設定し、INTYPEファイルで読み込みます。

TYPE Person
TYPE joe.Dept
TYPE sam.Company

この場合、OTT生成の構造体を使用するPro*C/C++アプリケーションでは、sam.Company、joe.DeptおよびPersonの3つの型を使用します。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で要求します。

通常は、それぞれの型が1つのスキーマで宣言されるため、INTYPEファイル内ですべての型の名前をスキーマ名で修飾するのが最も安全な方法です。

デフォルト名のマッピング

OTTでは、オブジェクト型または属性を表すC言語の識別子名の作成時に、その名前がデータベース・キャラクタ・セットから有効なC言語の識別子に変換されます。最初に、名前はデータベース・キャラクタ・セットからOTTで使用するキャラクタ・セットに変換されます。次に、その変換された名前の変換内容がINTYPEファイルに供給される場合は、その変換内容が使用されます。それ以外の場合、名前はCASEオプションで指定したコンパイラのキャラクタ・セットに1文字ずつ変換されます。この詳細を次に説明します。

OTTによってデータベース・エンティティ名が読み込まれると、データベース・キャラクタ・セットからOTTで使用するキャラクタ・セットに自動的に変換されます。OTTがデータベース・エンティティ名を正常に読み込むには、その名前のすべての文字がOTTのキャラクタ・セット内で検出される必要はあります。しかし、文字によっては2つのキャラクタ・セット間で異なるエンコーディングのことがあります。

必要な文字がOTTで使用するキャラクタ・セットにすべて含まれていることを保証するには、データベース・キャラクタ・セットと同じものを使用するのが最も簡単な方法です。ただし、OTTのキャラクタ・セットは、コンパイラのキャラクタ・セットのスーパーセットである必要があります。つまり、コンパイラのキャラクタ・セットが7ビットASCIIの場合、OTTのキャラクタ・セットはサブセットとして7ビットASCIIを含む必要があります。コンパイラのキャラクタ・セットが7ビットEBCDICの場合は、OTTのキャラクタ・セットはサブセットとして7ビットEBCDICを含む必要があります。OTTで使用されるキャラクタ・セットを指定するには、環境変数NLS_LANGを設定する方法と、プラットフォーム固有の他のメカニズムを使用する方法があります。

データベース・エンティティの名前は、OTTによって読み込まれると、OTTで使用するキャラクタ・セットからコンパイラのキャラクタ・セットに変換されます。名前の変換がINTYPEファイルで指定されている場合は、その変換が使用されます。

それ以外の場合、名前は次のように変換されます。

  1. 最初に、OTTのキャラクタ・セットがマルチバイト・キャラクタ・セットの場合、その名前にある、等価のシングルバイト文字を持つマルチバイト文字は、シングルバイト文字に変換されます。

  2. 次に、その名前は、OTTのキャラクタ・セットからコンパイラのキャラクタ・セットに変換されます。コンパイラのキャラクタ・セットは、US7ASCIIのように、シングルバイト・キャラクタ・セットです。

  3. 最後に、有効になっているCASEオプションに従って、文字の大/小文字が設定されます。そして、C言語の識別子で無効な文字、またはコンパイラのキャラクタ・セットに変換内容がない文字は、アンダースコアに置き換えられます。1文字でもアンダースコアに置き換えられると、OTTから警告メッセージが表示されます。名前に含まれる文字がすべてアンダースコアに置き換えられると、エラー・メッセージが表示されます。

文字単位の名前の変換では、コンパイラのキャラクタ・セットにあるアンダースコア、数字またはシングルバイト文字は変更されません。したがって、有効なC言語の識別子は変更されません。

たとえば、名前の変換では、ウムラウト(¨)の付いた「o」、または抑音符(`)の付いた「a」などのシングルバイトのアクセント文字を、「o」または「a」に変換できます。そして、マルチバイト文字を等価のシングルバイト文字に変換できます。名前の変換は、その名前に等価のシングルバイトがないマルチバイト文字があると、通常は失敗します。この場合、ユーザーは、INTYPEファイルでの名前の変換を指定する必要があります。

OTTでは、同じC言語の名前に複数のデータベース識別子がマップされたために発生する名前の重複は検出されません。また、データベース識別子がC言語のキーワードにマップされる場合に発生する命名の問題も検出されません。

制限

OTTを使用する場合は、次の制限が適用されます。

ファイル名比較

現在、OTTでは、2つのファイルが同じかどうかは、コマンドラインまたはINTYPEファイルでユーザーが指定したファイル名を比較して判断しています。ただし、2つのファイル名が同じファイルを参照するかどうかをOTTに認識させる必要がある場合は、問題が発生する可能性があります。たとえば、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ファイルでファイルを複数回記述するときは、各記述で正確に同じファイル名を使用する必要があります。