25 OCIでのObject Type Translatorの使用
この章では、Object Type Translator (OTT)について説明します。OTTを使用すると、データベース・オブジェクト・タイプや名前付きコレクション型をC構造体にマップして、OCIアプリケーションで使用できます。
この章には次のトピックが含まれます:
25.1 Object Type Translatorの使用方法
Object Type Translator (OTT)は、Oracleサーバーでユーザー定義型を使用するC言語アプリケーションを開発するのに役立ちます。
SQLのCREATE TYPE文を使用すると、オブジェクト型を作成できます。これらの型の定義をデータベースに格納しておき、データベースの表を作成するときに使用できます。これらの表を作成すると、OCIのプログラマは、表に格納されたオブジェクトにアクセスできます。
オブジェクト・データにアクセスするアプリケーションには、データをホスト言語形式で表現する機能が必要です。これは、オブジェクト型をC構造体として表現することによって実現できます。プログラマがデータベース・オブジェクト・タイプを表す構造体宣言を、手入力でコーディングすることは可能ですが、多くの型がある場合、この作業は時間がかかり、エラーを生む原因になることも少なくありません。OTTでは、適切な構造体宣言を自動的に生成することにより、このような手動のコーディングをしなくて済むようにします。OCIのアプリケーションでは、OTTで生成された初期化関数をコールします。
OTTは、格納済のデータ型を表す構造体を作成するのみでなく、オブジェクト型またはそのフィールドがNULLかどうかを示すパラレル・インジケータ構造体も生成します。
Object Type Translator (OTT)は、オブジェクト型と名前付きコレクション型のデータベース定義を、OCIアプリケーションに組み込むことができるC構造体宣言に変換します。
OTTを明示的に起動し、データベース型をC表現に変換する必要があります。
ほとんどのオペレーティング・システムでは、コマンドラインからOTTを起動します。これは、intypeファイルを入力として受け取り、outtypeファイル、1つ以上のCのヘッダー・ファイルおよびオプションの実装ファイルを生成します。OTTを起動するコマンドの例を次に示します。
ott userid=scott intype=demoin.typ outtype=demoout.typ code=c hfile=demo.h\
initfile=demov.c
このコマンドで、OTTをユーザー名scottでデータベースに接続します。ユーザーはパスワードの入力を求められます。
実装ファイル(demov.c)には、変換済のユーザー定義型の情報を含む型バージョン表を初期化する関数を格納します。
この章の後の項で、各パラメータについて詳しく説明します。
demoin.typファイルの例:
CASE=LOWER TYPE emptype
demoout.typファイルの例:
CASE = LOWER TYPE SCOTT.EMPTYPE AS emptype VERSION = "$8.0" HFILE = demo.h
この例のdemoin.typファイルには、TYPEが前に付く変換対象の型(TYPE emptypeなど)があります。outtypeファイルの構造体は、intypeファイルに似ており、OTTで取得した情報が追加されます。
OTTによる変換が終了すると、ヘッダー・ファイルには、intypeファイルで指定した各型のC構造体表現と、各型に対応したNULLインジケータ構造体が入っています。たとえば、例25-1に示すように、intypeファイルにリストされたemployeeタイプが定義されたとします。
OTTで生成されたヘッダー・ファイル(demo.h)には、その他の項目の中に、例25-2に示すような宣言が含まれます。
例25-3は、このコマンドで生成されたサンプルの実装ファイル(demov.c)に含まれている内容を示しています。
このintypeファイルのパラメータにより、生成した構造体に名前を付ける方法を制御します。この例では、構造体名emptypeが、データベース型名emptypeに一致しています。intypeファイル内の行CASE=lowerに従って、構造体名は小文字にします。
構造体宣言(OCIStringやOCIIndなど)のデータ型は、特殊なデータ型です。
この章の残りの各項では、OCIでのOTTの使用方法を説明します。その後に続く参照の項では、コマンドライン構文、パラメータ、intypeファイルの構造、ネストした#includeファイルの生成、スキーマ名の使用方法、デフォルトの名前マッピングおよび制限事項を説明します。
例25-1 intypeファイルにリストされたemployeeオブジェクト型の定義
CREATE TYPE emptype AS OBJECT
(
name VARCHAR2(30),
empno NUMBER,
deptno NUMBER,
hiredate DATE,
salary NUMBER
);
例25-2 生成されたヘッダー・ファイルdemo.hの内容
struct emptype
{
OCIString * name;
OCINumber empno;
OCINumber deptno;
OCIDate hiredate;
OCINumber salary;
};
typedef struct emptype emptype;
struct emptype_ind
{
OCIInd _atomic;
OCIInd name;
OCIInd empno;
OCIInd deptno;
OCIInd hiredate;
OCIInd salary;
};
typedef struct employee_ind employee_ind;
例25-3 demov.cファイルの内容
#ifndef OCI_ORACLE
#include <oci.h>
#endif
sword demov(OCIEnv *env, OCIError *err)
{
sword status = OCITypeVTInit(env, err);
if (status == OCI_SUCCESS)
status = OCITypeVTInsert(env, err,
"HR", 2,
"EMPTYPE", 7,
"$8.0", 4);
return status;
}
関連項目:
これらの型の詳細は、「OTTデータ型マッピング」を参照してください
25.1.1 データベースでの型の作成について
OTTを使用するときの最初のステップは、オブジェクト型または名前付きコレクション型を作成してデータベースに格納することです。
そのためには、SQLのCREATE TYPE文を使用します。
関連項目:
CREATE TYPE文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
25.1.2 OTTの起動について
OTTを起動するステップは、次のとおりです。OTTパラメータは、コマンドラインで、または構成ファイルをコールしたファイルで指定できます。
一部のパラメータは、intypeファイルでも指定できます。
1つのパラメータが複数箇所に指定されている場合は、コマンドラインのパラメータ値がintypeファイルの値より優先され、intypeファイルの値はユーザー定義の構成ファイルの値より優先され、ユーザー定義の構成ファイルの値は、デフォルトの構成ファイルの値より優先されます。
グローバル・オプション、つまり、コマンドラインのオプションまたはintypeファイルのTYPE文の前のオプションについては、intypeファイルの値がコマンドラインの値で上書きされます。(intypeファイルでグローバルとして指定できるオプションには、CASE、CODE、INITFILEおよびINITFUNCがあります。HFILEは含まれません。)TYPEを指定するintypeファイルのオプションは、特定の型にのみ適用されます。その型に適用される、コマンドラインで指定したそれ以外のオプションは上書きされます。TYPE person HFILE=p.hと入力した場合、オプションはpersonにのみ適用され、コマンドラインのHFILEは上書きされます。文はコマンドライン・パラメータとはみなされません。
25.1.2.2 構成ファイル
構成ファイルは、OTTパラメータが記述されているテキスト・ファイルです。
ファイル内の各非空白行には、1つのパラメータと、それに関連付けられた1つ以上の値が含まれています。1行に2つ以上のパラメータを指定した場合は、最初のパラメータのみが使用されます。構成ファイルの非空白行では、空白は使用できません。
構成ファイルは、コマンドラインで名前を指定できます。また、デフォルトの構成ファイルは常に読み取られます。このデフォルトの構成ファイルは、常に存在している必要がありますが、空でも構いません。デフォルトの構成ファイルの名前はottcfg.cfgであり、構成ファイルの位置はシステム固有の設定です。たとえば、Solarisでのファイル指定は、$ORACLE_HOME/precomp/admin/ottcfg.cfgです。詳細は、使用しているオペレーティング・システムのマニュアルを参照してください。
25.2 OTTのコマンドライン
ほとんどのオペレーティング・システムでは、コマンドラインからOTTを起動します。
入出力ファイルやデータベース接続情報などを指定できます。OTTの起動方法は、使用しているオペレーティング・システム固有のマニュアルを参照してください。
この項には次のトピックが含まれます。「OTTコマンドライン起動例」。
25.2.1 OTTコマンドライン起動の例
コマンドラインからのOTTを起動する方法を示します。
例25-4は、コマンドラインからのOTTの起動方法を示しています。
ノート:
等号(=)の両側には空白を挿入しないでください。
例25-4 OTTのコマンドラインからの起動
ott userid=bren intype=demoin.typ outtype=demoout.typ code=c \
hfile=demo.h initfile=demov.c
25.2.1.4 OUTTYPE
outtypeファイルの名前を指定します。
OTTでCヘッダー・ファイルを生成すると、変換された型の情報がouttypeファイルに書き込まれます。このファイルには、変換された各型のエントリが、バージョン文字列およびC表現を書き込んだヘッダー・ファイルとともに含まれています。
例25-4では、outtypeファイルの名前がdemoout.typに指定されています。
ノート:
outtypeのキーワードで指定されたファイルが存在している場合、そのファイルは、OTTが実行されると上書きされます。outtypeファイル名とintypeファイル名が同じ場合は、outtypeファイル内の情報でintypeファイルが上書きされます。
25.2.1.5 CODE
変換のターゲット言語を指定します。
次のオプションを使用できます。
-
C (ANSI_Cと等価)
-
ANSI_C (ANSI C対応)
-
KR_C (Kernighan & Ritchie C対応)
現在はデフォルト・オプションがないため、このパラメータは必須です。
構造体の宣言は、両方のCにおいて同一です。INITFILEファイルに定義されている初期化関数のスタイルは、KR_Cが使用されているかどうかによって異なります。INITFILE オプションが使用されていない場合、3つのオプションはすべて等価です。
25.2.1.6 HFILE
生成された構造体を書き込むCヘッダー・ファイルの名前を指定します。
例25-4では、生成される構造体はdemo.hと呼ばれるファイルに格納されます。
ノート:
キーワードhfileで既存のファイルを指定した場合は、OTTの実行時に上書きされますが、次のように例外が1つあります。OTTで生成されたファイルの内容がそのファイルの前の内容と同一の場合、OTTはそのファイルに実際には書き込みません。これにより、ファイルの変更時間を節約でき、LinuxおよびUNIXのmakeおよび他のオペレーティング・システムでの類似機能で、不必要な再コンパイルが実行されません。
25.3 intypeファイル
OTTの実行時に、intypeファイルはどのデータベース型の変換が必要であるかをOTTに指示します。
また、このファイルを使用して、生成される構造体の命名方法も指定できます。intypeファイルは、ユーザー作成ファイルでも、前回OTTを起動したときのouttypeファイルでもかまいません。intypeパラメータが使用されていない場合は、OTTの接続先のスキーマにあるすべての型が変換されます。
例25-5は、簡単なユーザー作成intypeファイルを示しています。
例25-5の詳細な説明は次のようになります。
第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を変換します。
TRANSITIVEパラメータの値としてFALSEを指定すると、OTTは、intypeファイルに指定されていない型は生成しません。
通常の大/小文字の区別がないSQL識別子は、intypeファイルでは、大/小文字のどのような組合せのつづりでもかまいません。また、引用符で囲みません。
CREATE TYPE "Person"などの大/小文字を区別して作成したSQL識別子を参照するには、TYPE "Person"などの引用符を使用します。SQL識別子は、宣言の際に引用符で囲んだ場合は、大/小文字が区別されます。引用符は、TYPE "CASE"などのOTT予約語であるSQL識別子の参照にも使用できます。そのため、名前を引用符で囲むときは、そのSQL識別子がCREATE TYPE Caseのように大/小文字を区別せずに作成されている場合、引用符で囲む名前は大文字にする必要があります。OTT予約語がSQL識別子の名前参照用に使用されているが、引用符で囲まれていない場合、OTTはintypeファイルに構文エラーをレポートします。
例25-5 ユーザー作成intypeファイルの内容
CASE=LOWER
TYPE employee
TRANSLATE SALARY$ AS salary
DEPTNO AS department
TYPE ADDRESS
TYPE item
TYPE "Person"
TYPE PURCHASE_ORDER AS p_o
関連項目:
-
intypeファイルの構造体の指定と使用可能なオプションの詳細は、「intypeファイルの構造体」を参照してください
25.4 OTTデータ型マッピング
OTTでデータベース型から生成したC構造体には、オブジェクト型の属性ごとに1つずつ対応する要素が含まれています。
属性のデータ型は、Oracleのオブジェクト・データ型で使用される型にマップされます。Oracle Databaseのデータ型には、事前定義済の基本型の集合が組み込まれています。これらのデータ型は、オブジェクト型やコレクションなどのユーザー定義型の作成をサポートします。
また、Oracle Databaseには、オブジェクト型属性をC構造体で表現するための事前定義済の型の集合も含まれています。たとえば、例25-6のようなオブジェクト型定義と、例25-7のようなOTTで生成した対応する構造体宣言があるとします。
CASE=LOWERで、タイプまたは属性名の明示的なマッピングがないと仮定すると、OTT出力は例25-7のようになります。
ここでは、構造体宣言のデータ型、OCIString、OCINumber、OCIDateおよびOCIIndを使用してオブジェクト型の属性のデータ型をマップしています。たとえば、empno属性のNUMBERデータ型は、OCINumberデータ型にマップされます。また、これらのデータ型は、バインド変数および定義変数の型としても使用できます。
例25-6 従業員用のオブジェクト型定義
CREATE TYPE employee AS OBJECT
( name VARCHAR2(30),
empno NUMBER,
deptno NUMBER,
hiredate DATE,
salary$ NUMBER);
例25-7 OTTで生成した構造体宣言
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;
関連項目:
インジケータの構造体(struct employee_ind)の説明は、「NULLインジケータ構造体」を参照してください
25.4.1 オブジェクト・データ型のCへのマッピングについて
この項では、Oracleのオブジェクト属性型とOTTで生成されるCの型とのマッピングを説明します。
前の「OTT型マッピングの例」では、様々なマッピングの例を示します。表25-1は、属性として使用できる型からOTT生成オブジェクト・データ型へのマッピング、および対応するOCI型コード値のリストです。
表25-1 オブジェクト型属性のオブジェクト・データ型マッピング
| オブジェクト属性の型 | Cマッピング | OCITypeCodeの値 |
|---|---|---|
|
BFILE |
OCIBFileLocator* |
OCI_TYPECODE_BFILE |
|
BLOB |
OCILobLocator *またはOCIBlobLocator * |
OCI_TYPECODE_BLOB |
|
CHAR(N)、CHARACTER(N)、NCHAR(N) |
OCIString * |
OCI_TYPECODE_CHAR (n)、OCI_TYPECODE_NCHAR |
|
CLOB、NCLOB |
OCILobLocator *またはOCIClobLocator * |
OCI_TYPECODE_CLOB、OCI_TYPECODE_NCLOB |
|
DATE |
OCIDate |
OCI_TYPECODE_DATE |
|
ANSI DATE |
OCIDateTime * |
OCI_TYPECODE_TIMESTAMP |
|
TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE |
OCIDateTime * |
OCI_TYPECODE_TIMESTAMP、OCI_TYPECODE_TIMESTAMP_TZ、OCI_TYPECODE_TIMESTAMP_LTZ |
|
INTERVAL YEAR TO MONTH、INTERVAL DAY TO SECOND |
OCIInterval * |
OCI_TYPECODE_INTERVAL_YM、OCI_TYPECODE_INTERVAL_DS |
|
DEC、DEC(N)、DEC(N,N) |
OCINumber |
OCI_TYPECODE_DECIMAL (p) |
|
DECIMAL、DECIMAL(N)、DECIMAL(N,N) |
OCINumber |
OCI_TYPECODE_DECIMAL (p) |
|
FLOAT、FLOAT(N)、DOUBLE PRECISION |
OCINumber |
OCI_TYPECODE_FLOAT (b) |
|
BINARY_FLOAT |
float |
OCI_TYPECODE_BFLOAT |
|
BINARY_DOUBLE |
double |
OCI_TYPECODE_BDOUBLE |
|
INT、INTEGER、SMALLINT |
OCINumber |
OCI_TYPECODE_INTEGER、OCI_TYPECODE_SMALLINT |
|
ネストしたオブジェクト型 |
ネストしたオブジェクト型のCの名前 |
OCI_TYPECODE_OBJECT |
|
ネストした表 |
OCITable * |
OCI_TYPECODE_TABLE |
|
NUMBER、NUMBER(N)、NUMBER(N,N) |
OCINumber |
OCI_TYPECODE_NUMBER(p, s) |
|
NUMERIC、NUMERIC(N)、NUMERIC(N,N) |
OCINumber |
OCI_TYPECODE_NUMBER(p, s) |
|
RAW(N) |
OCIRaw * |
OCI_TYPECODE_RAW |
|
REAL |
OCINumber |
OCI_TYPECODE_REAL |
|
REF |
OCIRef * |
OCI_TYPECODE_REF |
|
VARCHAR(N) |
OCIString * |
OCI_TYPECODE_VARCHAR (n) |
|
VARCHAR2(N)、NVARCHAR2(N) |
OCIString * |
OCI_TYPECODE_VARCHAR2 (n)、OCI_TYPECODE_NVARCHAR2 |
|
OCIArray * |
OCI_TYPECODE_VARRAY | |
| コレクション | OCIColl * | OCI_TYPECODE_NAMEDCOLLECTION |
ノート:
REF、VARRAYおよびNESTED TABLE型の場合、OTTでは、typedefが生成されます。このtypedefで宣言された型は、構造体宣言でデータ・メンバーの型として使用されます。例は、「OTT型マッピングの例」を参照してください。
オブジェクト型にREFまたはコレクション型の属性が含まれている場合は、最初にREFまたはコレクション型のtypedefが生成されます。次に、オブジェクト型に対応する構造体宣言が生成されます。構造体には、REFまたはコレクション型へのポインタを型に持つ要素が含まれます。
あるオブジェクト型に、別のオブジェクト型を持つ属性が含まれている場合、OTTではネストした型が最初に生成されます(TRANSITIVE=TRUEの場合)。次に、オブジェクト型属性が、ネストしたオブジェクト型である型のネストした構造体にマッピングされます。
OTTがオブジェクト以外のデータベース属性の型をマップするOracleのCデータ型は構造体で、OCIDate以外は不透明です。
25.4.2 OTT型マッピングの例
データベース型の指定時にOTTで作成される各種の型マッピングを示します。
例25-9は、例25-8に示すデータベース型の指定時に、OTTで作成される様々な型のマッピングを示しています。
intypeファイルには次が含まれています。
CASE = LOWER TYPE many_types
OTTでは、例25-9に示すようなC構造体が生成されます。
ノート:
例25-9では、構造体に関する説明として、コメントを付けています。これらのコメントは、実際のOTT出力の一部ではありません。
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;
...
}例25-8 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 other_type AS OBJECT (object_number NUMBER); 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));
例25-9 オブジェクト型定義から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; /* used in many_types */
typedef OCITable my_table; /* used in many_types*/
typedef OCIRef other_type_ref;
struct object_type /* used in 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
関連項目:
25.4.3 NULLインジケータ構造体
OTTでデータベース・オブジェクト・タイプを表現するC構造体が生成されるたびに、対応するNULLインジケータ構造体も生成されます。
C構造体にオブジェクト型を選択するとき、パラレル構造体の中にNULLインジケータ情報を選択できます。
たとえば、例25-9では、次の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属性)、その属性のインジケータ・エントリは、ネストしたオブジェクト型(TRANSITIVE=TRUEの場合)に対応しているNULLインジケータ構造体(object_type_ind)です。
VARRAYとNESTED TABLEには、各要素のNULL情報が含まれています。
NULLインジケータ構造体のその他の要素のデータ型は、すべてOCIIndです。
関連項目:
アトミックNULLの詳細は、「NULLインジケータ構造体」を参照してください
25.4.4 OTTによる型の継承のサポート
オブジェクトの型の継承をサポートするために、OTTは、新しい属性を宣言する前に、継承される属性を、特別な名前_superを持つカプセル化された構造体内で宣言することで、オブジェクトのサブタイプを表すC構造体を生成します。
これによって、スーパータイプを継承するオブジェクトのサブタイプについては、その構造体の第1要素が_superと命名され、サブタイプの各属性に対応する要素がその後に続きます。この_superと命名された要素の型がスーパータイプの名前です。
たとえば、例25-10に示すように、サブタイプStudent_tとEmployee_tを持つPerson_t型があるとします。
また、例25-11に示す内容のintypeファイルもあります。
例25-12に示すように、OTTでは、Person_t、Student_tおよびEmployee_tに対するC構造体とそれぞれのNULLインジケータ構造体が生成されます。
前述のCマッピング変換によって、サブタイプのインスタンスからCのスーパータイプのインスタンスへのアップキャストが簡単かつ適切に行われます。たとえば、次のようにします。
STUDENT_T *stu_ptr = some_ptr; /* some STUDENT_T instance */ PERSON_T *pers_ptr = (PERSON_T *)stu_ptr; /* upcasting */
同様に、NULLインジケータ構造体が生成されます。スーパータイプPerson_tのNULLインジケータ構造体の最初の要素は_atomicで、サブタイプEmployee_tおよびStudent_tのNULLインジケータ構造体の最初の要素は_superであることに注意してください(サブタイプの場合、アトミック要素は生成されません)。
例25-10 オブジェクト型とサブタイプの定義
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));
例25-11 intypeファイルの内容
CASE=SAME TYPE EMPLOYEE_T TYPE STUDENT_T TYPE PERSON_T
例25-12 OTTによる型に対する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_ind;
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
この項には次のトピックが含まれます: 置換可能なオブジェクト属性。
25.4.4.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オブジェクト自体から取得できます。「OCIObjectGetInd()」を参照してください。
型がFINALに定義されている場合、サブタイプは使用できません。したがって、FINAL型の属性は置換できません。その場合、マッピングは前述のとおりになり、属性構造体はインラインです。型が変更され、NOT FINALに定義される場合は、マッピングを変更する必要があります。新しいマッピングは、OTTを再実行すると生成されます。
関連項目:
25.5 outtypeファイル
outtypeファイルは、OTTコマンドラインで名前が付けられます。
OTTでCヘッダー・ファイルが生成されると、変換の結果がouttypeファイルに書き込まれます。このファイルには、変換された各型のエントリが、バージョン文字列およびC表現を書き込んだヘッダー・ファイルとともに含まれています。
OTTの1回の実行で生成されたouttypeファイルは、それ以降のOTTの起動ではintypeファイルとして使用できます。
たとえば、例25-13に示すように、例25-5で使用した簡単なintypeファイルがあるとします。
この例では、OTTで生成するC識別子の大/小文字の区別を指定し、変換する型をリストして指定しています。これらの型のうちの2つについては、ネーミング規則が指定されています。
例25-14は、OTT実行後のouttypeファイルを示しています。
outtypeファイルの内容を調べると、intype指定に含まれていなかった型がリストされていることに気づきます。たとえば、person型が次のように変換されることのみ指定されたintypeファイルがあるとします。
CASE = LOWER TYPE PERSON
ただし、このperson型の定義にaddress型の属性が含まれているため、outtypeファイルには、PERSONとADDRESSの両方のエントリが含まれます。person型を完全に変換するには、最初にaddressを変換する必要があります。
パラメータTRANSITIVEがTRUEに設定されている(デフォルトの)場合、OTTは、変換を実行する前にintypeファイル内の型の依存性を分析してから、必要に応じて他の型を変換します。
例25-13 intypeファイルの内容
CASE=LOWER
TYPE employee
TRANSLATE SALARY$ AS salary
DEPTNO AS department
TYPE ADDRESS
TYPE item
TYPE "Person"
TYPE PURCHASE_ORDER AS p_o
例25-14 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
25.6 OCIアプリケーションでのOTTの使用方法について
Oracleサーバー内のオブジェクトにアクセスするOCIアプリケーションでは、OTTで生成したCヘッダー・ファイルと実装ファイルを使用できます。
ヘッダー・ファイルは、#include文でOCIコードに取り込みます。
OCIアプリケーションでは、ヘッダー・ファイルを組み込んだ後、ホスト言語形式のオブジェクト・データにアクセスし、操作できます。
図25-1は、最も単純なアプリケーションのOCIでOTTを使用する場合のステップを示しています。
-
SQLを使用してデータベースに型定義を作成します。
-
OTTで、オブジェクト型と名前付きコレクション型のC表現を含むヘッダー・ファイルを生成します。
INITFILEオプションで命名された実装ファイルも生成します。 -
アプリケーションを記述します。OCIアプリケーションでユーザーが記述したコードで、
INITFUNC関数を宣言してコールします。 -
ヘッダー・ファイルをOCIソース・コード・ファイルにインクルードします。
-
OTTで生成された実装ファイルを含めて、OCIアプリケーションがコンパイルされ、OCIライブラリにリンクされます。
-
OCI実行可能ファイルをOracle Databaseに対して実行します。
25.6.1 OCIでのオブジェクトへのアクセスおよび操作について
アプリケーション内部では、OCIプログラムでバインド操作と定義操作を実行できます。そのためには、OTTで生成したヘッダー・ファイルに示されている型で宣言したプログラム変数を使用します。
たとえば、アプリケーションでSQLのSELECT文を使用して、オブジェクトへのREFをフェッチし、適切なOCI関数を使用してそのオブジェクトを確保します。オブジェクトを確保した後、その他のOCI関数を使用してそのオブジェクトの属性データにアクセスし、操作できます。
OCIには、オブジェクト型の属性と名前付きコレクション型で操作するために特別に設計された、一連のデータ型マッピング関数および操作関数が組み込まれています。
使用可能な関数の例を次に示します。
-
OCIStringSize()は、OCIString文字列のサイズを取得します。 -
OCINumberAdd()は、2つのOCINumber数値を加算します。 -
OCILobIsEqual()は、2つのLOBロケータが等しいかどうかを比較します。 -
OCIRawPtr()は、ロー・データ型OCIRawへのポインタを取得します。 -
OCICollAppend()は、コレクション型(OCIArrayまたはOCITable)に要素を追加します。 -
OCITableFirst()は、NESTED TABLE(OCITable)の最初の既存要素の索引を戻します。 -
OCIRefIsNull()は、REF(OCIRef)がNULLかどうかをテストします。
これらの関数の詳細は、このマニュアルの他の章を参照してください。
25.6.2 初期化関数のコール
OTTは、必要に応じてC初期化関数を生成します。初期化関数では、プログラムで使用されている各オブジェクト型について、どのバージョンの型が使用されているかを環境に通知します。
INITFUNCオプションでOTTを起動する場合は、初期化関数の名前を指定するか、初期化関数が含まれている実装ファイル(INITFILE)の名前に基づいてデフォルト名を選択できます。
初期化関数には、環境ハンドル・ポインタとエラー・ハンドル・ポインタの2つの引数があります。一般的に、使用する初期化関数は1つですが、必ずしもそうである必要はありません。プログラムにコンパイル済の個別のピースがあり、異なる型を要求する場合は、各ピースに対して初期化関数が含まれた1つの初期化ファイルをそれぞれ要求して、OTTを個別に実行できます。
たとえば、OCIEnvCreate()をコールして、明示的なOCIオブジェクト・コールによって環境ハンドルを作成した後は、初期化関数も明示的にコールする必要があります。明示的に作成した環境ハンドルそれぞれに対して、必ずすべての初期化関数をコールする必要があります。これによって、各ハンドルは、プログラム全体で使用しているすべてのOracleデータ型にアクセスできます。
EXEC SQL CONTEXT USEやEXEC SQL CONNECTなどの埋込みSQL文を使用して環境ハンドルを暗黙的に作成する場合、ハンドルは暗黙的に初期化されるため、初期化関数をコールする必要はありません。これは、Pro*C/C++をOCIアプリケーションと結合している場合にのみ適用します。
次に、初期化関数の例を示します。
例25-15に示すような内容を含むintypeファイル、ex2c.typがあるとします。
例25-16に示すように、コマンドラインからOTTを起動し、初期化関数を指定します。
OTTでは、例25-17に示すように、ex2cv.cファイルが生成されます。
関数ex2cvによって、型バージョン表が作成され、BREN.PERSON型とBREN.ADDRESS型が挿入されます。
プログラムで明示的に環境ハンドルを作成する場合、明示的に作成するハンドルごとに初期化関数をコールする必要があるので、すべての初期化関数を生成し、コンパイルし、リンクしてください。プログラムが明示的に環境ハンドルを作成しない場合、初期化関数は必要ありません。
OTTで生成したヘッダー・ファイルを使用するプログラムでは、同時に生成された初期化関数も使用する必要があります。OTTでヘッダー・ファイルを生成し、プログラムで環境ハンドルを明示的に作成した場合は、実装ファイルもコンパイルして、実行可能ファイルにリンクする必要があります。
例25-15 ex2c.typという名前のintypeファイルの内容
TYPE BREN.PERSON TYPE BREN.ADDRESS
例25-16 OTTの起動と初期化関数の指定
ott userid=bren intype=ex2c outtype=ex2co hfile=ex2ch.h initfile=ex2cv.c
例25-17 ex2cv.cという名前のOTTで生成したファイルの内容
#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,
"BREN", 5,
"PERSON", 6,
"$8.0", 4);
if (status == OCI_SUCCESS)
status = OCITypeVTInsert(env, err,
"BREN", 5,
"ADDRESS", 7,
"$8.0", 4);
return status;
}
関連項目:
25.6.3 初期化関数のタスク
C初期化関数は、OTTで処理する型のバージョン情報を提供します。C初期化関数は、OTTで処理する各オブジェクト・データ型の名前とバージョン識別子を型バージョン表に追加します。
型バージョン表は、Oracle Databaseの型マネージャが、特定のプログラムで使用する型のバージョンを特定するときに使用します。異なる時期にOTTで生成した異なる複数の初期化関数によって、型バージョン表に同じ型が複数回追加される可能性があります。型が複数回追加される場合、Oracle Databaseでは、毎回同じバージョンの型が確実に登録されるようにします。
初期化関数に対して関数プロトタイプを宣言し、その関数をコールするのは、OCIプログラマの役割です。
ノート:
Oracle Databaseのカレント・リリースでは、型ごとにバージョンは1つのみです。型バージョン表の初期化は、Oracle Databaseの今後のリリースとの互換性を保つためにのみ必要です。
25.7 OTTリファレンス
OTTコマンドラインまたはCONFIGファイルで指定できるパラメータは、OTTの動作を制御します。また、一部のパラメータは、intypeファイルにも指定できます。
この項では、次の項目について詳しく説明します。
この項では、次の規則を使用してOTTの構文を説明します。
-
イタリックの文字列は、ユーザーが指定する変数またはパラメータです。
-
大文字の文字列は、そのとおりに入力する文字列です。ただし、大/小文字は区別されないため、小文字で入力しても有効です。
-
OTTキーワードは、例やヘッダーでは小文字の固定幅フォントでリストされていますが、本文では、目立つように大文字で印刷されています。
-
大カッコ[...]で囲んだ項目は、オプション項目です。
-
1つの項目(あるいはカッコで囲まれた複数の項目)の直後の省略記号(...)は、その項目を何度も繰り返し指定できることを示します。
-
これ以外の句読点記号は、示されているとおりに入力します。「.」や「@」などが含まれます。
25.7.1 OTTコマンドラインの構文
OTTコマンドライン・インタフェースは、OTTを明示的に起動してデータベース型をC構造体に変換するときに使用します。
オブジェクトを使用するOCIアプリケーションを開発する場合は、必ずこのインタフェースが必要です。
OTTコマンドライン文は、キーワードOTTと、その後に続くOTTパラメータのリストによって構成されます。
OTTコマンドラインの文で指定できるパラメータは、次のとおりです。
[userid=username/password[@db_name]] [intype=filename] outtype=filename code=C|ANSI_C|KR_C [hfile=filename] [errtype=filename] [config=filename] [initfile=filename] [initfunc=filename] [case=SAME|LOWER|UPPER|OPPOSITE] [schema_name=ALWAYS|IF_NEEDED|FROM_INTYPE] [transitive=TRUE|FALSE] [URL=url]
ノート:
一般に、ottコマンドの後に続くパラメータの順序は重要ではありません。OUTTYPEおよびCODEの各パラメータのみは常に必須です。
HFILEパラメータは、ほとんどの場合に使用されます。コマンドラインから省略すると、HFILEをintypeファイルの型ごとに個別に指定する必要があります。OTTでは、intypeファイルにリストされていない型を変換する必要があると判断すると、エラーをレポートします。したがって、HFILEパラメータを省略できるのは、intypeファイルが以前にOTT outtypeファイルとして生成された場合にかぎります。
intypeファイルを省略すると、スキーマ全体が変換されます。OTTパラメータの説明は後続の項を参照してください。
OTTコマンドライン文の例を次に示します(パスワードの入力を求められます)。
ott userid=marc intype=in.typ outtype=out.typ code=c hfile=demo.h\ errtype=demo.tls case=lower
次の各項では、OTTコマンドラインの各パラメータについて説明します。
関連項目:
25.7.2 OTTパラメータ
OTTコマンドラインにパラメータを入力するときの書式は、次のとおりです。
parameter=value
この書式で、parameterはリテラル・パラメータ文字列であり、valueは有効なパラメータ設定値です。リテラル・パラメータ文字列は大/小文字を区別しません。
コマンドラインのパラメータは、空白またはタブのいずれかを使用して区切ります。
また、パラメータは構成ファイル内でも指定できます。ただし、この場合、行の中に空白を入れることはできないため、各パラメータは独立した行に指定する必要があります。さらに、パラメータCASE、HFILE、INITFUNCおよびINITFILEは、intypeファイルに入れることができます。
25.7.2.1 USERID
USERIDパラメータでは、データベース・ユーザー名、パスワードおよびオプションのデータベース名(Oracle Net Servicesのデータベース指定文字列)を指定します。
データベース名を省略すると、デフォルトのデータベースが使用されます。このパラメータの構文は、次のとおりです。
userid=username/password[@db_name]
USERIDパラメータはオプションです。省略した場合、OTTは自動的にユーザーOPS$usernameでデフォルトのデータベースへの接続を試みます。ここで、usernameは、ユーザーのオペレーティング・システムのユーザー名です。これが最初のパラメータである場合、次に示すように、USERID=、パスワードおよびデータベース名を省略できます。
ott username ...
セキュリティ上の問題から、ユーザー名を入力するときのみ残りの項目を入力するよう求められます。
usernameとdb_name (スキーマ名)の組合せが追加され、OCIContextGetValue()コールのキーとして使用されます(これにより、Oracle Database 21cリリースでの64バイトの最大長がサポートされます)。21cリリースでは、この最大長は243バイトをサポートするように拡張されています(ピリオド(.)用の1文字は含みません)。
25.7.2.2 INTYPE
INTYPEパラメータでは、オブジェクト型指定のリストの読取り元ファイルの名前を指定します。読み取ったリストにある型が、OTTによって変換されます。
このパラメータの構文は、次のとおりです。
intype=filename
USERIDが第1パラメータ、INTYPEが第2パラメータで、USERID=を省略した場合は、INTYPE=も省略できます。INTYPEパラメータが指定されていない場合は、ユーザーのスキーマの型すべてが変換されます。
ott username filename...
intypeファイルは、型宣言のmakefileと考えることができます。C構造体宣言の必要な型をリストします。
コマンドラインまたはintypeファイルのファイル名に拡張子がない場合は、「TYP」や「.typ」などのオペレーティング・システム固有の拡張子が追加されます。
関連項目:
intypeファイルの書式の説明は、「intypeファイルの構造体」を参照してください
25.7.2.3 OUTTYPE
OUTTYPEパラメータは、OTTが処理するすべてのオブジェクト・データ型の型情報を書き込むファイルの名前を指定します。
これには、intypeファイルで明示的に指定したすべての型が含まれます。さらに、変換対象である他の型の宣言で使用しているために変換された型が含まれる場合もあります(TRANSITIVE=TRUEの場合)。このファイルは、それ以後にOTTを起動するときにintypeファイルとして使用できます。
outtype=filename
INTYPEパラメータとOUTTYPEパラメータが同一のファイルを参照している場合、intypeファイルの古い情報は、新しいINTYPEパラメータの情報に置き換えられます。これは、型の変更から開始し、型宣言の生成、ソースコードの編集、プリコンパイル、コンパイル、デバッグに至るサイクルで、同一のintypeファイルを繰り返し使用するときに便利です。
パラメータOUTTYPEは必ず指定してください。
コマンドラインまたはouttypeファイルのファイル名に拡張子がない場合は、「TYP」や「.typ」などのオペレーティング・システム固有の拡張子が追加されます。
25.7.2.4 CODE
CODE=C、CODE=KR_CまたはCODE=ANSI_Cとして指定されるOTT出力の目的ホスト言語です。
「CODE=C」は「CODE=ANSI_C」と等価です。
CODE=C|KR_C|ANSI_C
このパラメータは、デフォルト値がないので必ず指定する必要があります。
25.7.2.5 INITFILE
INITFILEパラメータでは、OTTで生成した初期化ファイルを書き込むファイルの名前を指定します。
このパラメータを省略すると、初期化関数は生成されません。
Pro*C/C++プログラムの場合、必要な初期化はSQLLIBランタイム・ライブラリによって実行されるため、INITFILEは不要です。OCIプログラムのユーザーは、INITFILEファイルをコンパイルおよびリンクし、環境ハンドルの作成時に初期化ファイル関数をコールする必要があります。
コマンドラインまたはintypeファイルで指定したINITFILEファイル名に拡張子がない場合は、「C」や「.c」などのオペレーティング・システム固有の拡張子が追加されます。
initfile=filename25.7.2.6 INITFUNC
INITFUNCパラメータは、OCIプログラムのみで使用します。
OTTで生成する初期化関数の名前を指定します。このパラメータを省略すると、INITFILEの名前から初期化関数の名前が付けられます。
initfunc=filename25.7.2.7 HFILE
HFILEパラメータは、intypeファイルに記述した型の宣言でインクルード(.h)ファイルを指定しなかった場合に、OTTによって生成されるインクルード・ファイルの名前を指定します。
intypeファイルで各型のインクルード・ファイルを個々に指定していない場合は、このパラメータが必要です。また、intypeファイルに記述していない型を、2つ以上の異なるファイルで宣言されている他の型で使用し、TRANSITIVE=TRUEの場合は、intypeファイルに記述していない型も生成する必要があります。そのような場合もこのパラメータが必要です。
コマンドラインまたはintypeファイルで指定したHFILEファイル名に拡張子がない場合は、「H」や「.h」などのオペレーティング・システム固有の拡張子が追加されます。
hfile=filename25.7.2.8 CONFIG
CONFIGパラメータでは、共通で使用するパラメータ指定をリストしたOTT構成ファイルの名前を指定します。
また、パラメータ指定は、オペレーティング・システムによって異なる位置にあるシステム構成ファイルから読み取られます。残りのすべてのパラメータ指定は、コマンドラインまたはintypeファイルで指定する必要があります。
config=filename ノート:
CONFIGパラメータは、CONFIGファイルでは使用できません。
25.7.2.9 ERRTYPE
ERRTYPEパラメータを指定すると、OTTでは、intypeファイルのリストが、すべての情報メッセージおよびエラー・メッセージとともにERRTYPEファイルに書き込まれます。
情報メッセージおよびエラー・メッセージは、ERRTYPEパラメータを指定したかどうかに関係なく、標準出力に送信されます。
実質的に、ERRTYPEファイルはエラー・メッセージが追加されたintypeファイルのコピーです。ほとんどの場合、エラー・メッセージにはエラーの原因となったテキストへのポインタが示されます。
コマンドラインまたはintypeファイルで指定したERRTYPEファイル名に拡張子がない場合は、「TLS」や「.tls」などのオペレーティング・システム固有の拡張子が追加されます。
errtype=filename25.7.2.10 CASE
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
その場合、intypeファイルで指定された大/小文字に続いて、OTTでは次の行が生成されます。
struct wOrKeR {...};
intypeファイルに記述されていない、大/小文字の区別のないSQL識別子は、CASE=SAME,の場合は大文字で、CASE=OPPOSITEの場合は小文字で指定されます。宣言されるとき引用符で囲まれていないSQL識別子の場合、大/小文字の区別はありません。
25.7.2.11 SCHEMA_NAMES
SCHEMA_NAMESパラメータは、デフォルト・スキーマに基づいた型のデータベース名を、outtypeファイル内のスキーマ名で修飾する場合に、制御を行います。
OTTで生成したouttypeファイルには、型名も含めて、OTTで処理された型の情報が含まれています。
関連項目:
25.7.2.12 TRANSITIVE
TRANSITIVEパラメータの値は、TRUE (デフォルト)またはFALSEのいずれかです。
intypeファイルで明示的にリストされていない型の依存性が変換対象かどうかを示します。
TRANSITIVE=TRUEが指定されている場合は、他の型で必要でintypeファイルで記述されていない型が生成されます。
TRANSITIVE=FALSEが指定されている場合は、intypeファイルに指定されていない型は生成されません。生成した他の型の属性型として使用されている場合でも生成されません。
25.7.2.13 URL
URLパラメータの場合、OTTでは、JavaインタフェースであるJDBC (Java Database Connectivity)を使用してデータベースに接続します。
URLパラメータのデフォルト値は次のとおりです。
URL=jdbc:oracle:oci8:@
OCI8ドライバは、Oracle Databaseのインストールでクライアント側で使用します。
JDBCシン・ドライバ(Oracle Databaseをインストールしない場合にクライアント側で使用するJavaドライバ)を指定するには、次のURLパラメータの構文を使用します。
URL=jdbc:oracle:thin:@host:port:sid
hostはデータベースが実行されているホストの名前、portはポート番号、sidはOracle SIDです。
25.7.3 OTTパラメータの指定可能な場所
OTTパラメータは、コマンドラインまたはコマンドラインで名前が付けられたCONFIGファイル、あるいはその両方で指定できます。
パラメータの一部は、intypeファイルでも指定できます。
OTTは、次のように起動します。
ott username/password parameters
コマンドラインのパラメータの1つが次のパラメータである場合、構成ファイルfilenameからその他のパラメータが読み取られます。
config=filename
さらに、パラメータは、オペレーティング・システムによって異なる位置にあるデフォルトの構成ファイルから読み取られます。このファイルの存在は必要ですが、空でもかまいません。構成ファイルのパラメータは、スペースなしで、1行につき1つ表示してください。
引数を指定せずにOTTを実行すると、オンライン・パラメータ・リファレンスが表示されます。
変換されるOTTの型は、INTYPEパラメータで指定したファイルで命名されます。パラメータのCASE、INITFILE、INITFUNCおよびHFILEは、intypeファイルに含めることもできます。OTTで生成したouttypeファイルにはCASEパラメータが含まれ、初期化ファイルが生成されている場合は、INITFILEおよびINITFUNCの各パラメータが含まれます。outtype ファイルでは、型ごとにそれぞれHFILEを指定します。
OTTコマンドの大/小文字区別は、オペレーティング・システムによって異なります。
25.7.4 intypeファイルの構造体
intypeおよびouttypeファイルは、OTTで変換する型をリストし、型名や属性名を有効なC識別子に変換する方法を判断するのに必要な情報すべてを提供します。
これらのファイルには、1つ以上の型指定を記述します。また、次のオプションを指定する場合もあります。
-
CASE -
HFILE -
INITFILE -
INITFUNC
CASE、INITFILEまたはINITFUNCオプションを指定する場合は、すべての型指定よりも前に指定する必要があります。これらのオプションをコマンドラインとintypeファイルの両方に指定した場合は、コマンドラインの値が使用されます。
この項には次のトピックが含まれます。「intypeファイルの型指定」。
関連項目:
簡単なユーザー定義のintypeファイルの例、およびintypeファイルからOTTで生成される完全なouttypeファイルの例は、「outtypeファイル」を参照してください
25.7.4.1 intypeファイルの型指定
intypeファイルでの型指定によって、変換対象のオブジェクト・データ型の名前が指定されます。
また、outtypeでの型指定によって、変換済のオブジェクト・データ型の名前が指定されます。
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- Oracle Databaseオブジェクト・データ型の名前です。 -
type_identifier- 型を表すのに使用するC識別子です。type_identifierを省略すると、デフォルトの名前マッピング・アルゴリズムが使用されます。 -
version_stringは、OTTの以前の起動によってコードが生成されたときに使用された型のバージョン文字列です。バージョン文字列はOTTによって生成され、outtypeファイルに書き込まれます。このファイルは、後でOTTを実行するときにintypeファイルとして使用できます。バージョン文字列はOTTの操作には影響しませんが、最終的にこれを使用して、起動中のプログラムで使用されるオブジェクト・データ型のバージョンが選択されます。
-
hfile_name- 該当する構造体の宣言またはクラスが現れるヘッダー・ファイルの名前です。hfile_nameを省略すると、宣言の生成時には、コマンドラインのHFILEパラメータで指定したファイルが使用されます。 -
member_name-identifierに変換される属性(データ番号)の名前です。 -
identifierはユーザー・プログラムの属性を表すために使用されるCの識別子です。識別子は、任意の数の属性に対してこの方法で指定できます。指定していない属性については、デフォルトの名前マッピング・アルゴリズムが使用されます。
オブジェクト・データ型は、次のいずれかの場合に変換する必要があります。
-
intypeファイルに指定されています。
-
変換が必要な別の型を宣言する場合、および
TRANSITIVE=TRUEの場合は必須です。
明示的に記述していない型があり、その型が、正確に1つのファイルのみに宣言した型で必要だとします。この場合、OTTでは、明示的に記述していない型の変換結果は、それを必要とする明示的に宣言した型と同じファイルに書き込まれます。
明示的に記述していない型が、複数の異なるファイルの型の宣言に必要な場合、OTTでは、この必須の型の変換結果は、グローバルなHFILEファイルに書き込まれます。
関連項目:
version_stringコンポーネントに関連するintypeファイルのネーミングの詳細は、「デフォルトの名前のマッピング」を参照してください。
25.7.5 ネストされたインクルード・ファイルの生成
OTTで生成した各HFILEでは、#includeディレクティブを使用して、他の必要なファイルをインクルードし、#defineディレクティブを使用して、ファイル名から構成された記号を定義します。これは、HFILEがインクルードされているかどうかを判断するために使用できます。
たとえば、データベースに例25-18に示すような型があるとします。
intypeファイルの内容を例25-19に示します。
例25-20に示すコマンドを含むOTTを起動する場合、例25-21および例25-22に示すヘッダー・ファイルが生成されます。
ヘッダー・ファイルtott95b.hの内容を例25-21に示します。
ヘッダー・ファイルtott95a.hの内容を例25-22に示します。
例25-21では、TOTT95B_ORACLEという記号を最初に定義しています。そのため、プログラマは、例25-23に示すように、構造体を使用してtott95b.hを条件付きで組み込むことができます。その場合、tott95b.hがincludeファイルに依存しているかどうかを考慮する必要はありません。
この方法によって、プログラマは、適当なファイル(たとえばfoo.h)からtott95b.hを組み込むことができます。その際、tott95b.hが、foo.hに組み込まれるその他のファイルにも組み込まれるかどうかは、わかっていなくてもかまいません。
記号TOTT95B_ORACLEの定義の後に、ファイルoci.hがインクルードされます。OTT生成のすべてのHFILEには、Pro*C/C++やOCIのプログラマに役立つ型と関数の宣言が含まれたoci.hがインクルードされます。OTTが#includeディレクティブに山括弧を使用するのは、この場合のみです。
次に、ファイルtott95a.hを組み込みます。このファイルを組み込む理由は、tott95b.hに必要な「struct px1」の宣言が入っているからです。ユーザーのintypeファイルで、1つ以上のファイルに型宣言を書き込むように要求すると、OTTでは、他のファイルのうちどれを各HFILEに組み込むかを判断し、必要な#includesディレクティブを生成します。
このOTTの#includeディレクティブで、引用符が使用されていることに注意してください。tott95b.hを組み込むプログラムをコンパイルするとき、tott95a.hの検索は、ソース・プログラムが検出された場所から始まり、それ以降は実装定義の検索規則に従います。この方法でtott95a.hを検索できない場合、intypeファイルでtott95a.hの位置を指定するには、完全なファイル名(/で始まるLinuxまたはUNIXの絶対パス名など)を使用する必要があります。
例25-18 OTTがインクルード・ファイルをどのように生成するかを示すオブジェクト型定義
create type px1 AS OBJECT (col1 number, col2 integer); create type px2 AS OBJECT (col1 px1); create type px3 AS OBJECT (col1 px1);
例25-19 intypeファイルの内容
CASE=lower type pxl hfile tott95a.h type px3 hfile tott95b.h
例25-20 OTTのコマンドラインからの起動
ott scott tott95i.typ outtype=tott95o.typ code=c
例25-21 ヘッダー・ファイル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
例25-22 ヘッダー・ファイル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
例25-23 ヘッダー・ファイルtott95b.hを条件付きで組み込むために使用する構造体
#ifndef TOTT95B_ORACLE #include "tott95b.h" #endif
25.7.6 SCHEMA_NAMESの使用方法
SCHEMA_NAMESパラメータは、OTTが接続されたデフォルト・スキーマに基づいて付けた型の名前を、outtypeファイル内のスキーマ名で修飾するかどうかを決定します。
このパラメータは、OTTが接続されたデフォルト・スキーマに基づいて付けた型の名前を、outtypeファイル内のスキーマ名で修飾するかどうかを決定します。
デフォルト・スキーマ以外のスキーマに基づいて付けた型の名前は、常にouttypeファイル内のスキーマ名で修飾されます。
スキーマ名で修飾するかしないかで、プログラム実行中に型がどのスキーマで検索されるかが決定します。
次の3通りの設定があります。
-
schema_names=ALWAYS(デフォルト)outtypeファイル内のすべての型名をスキーマ名で修飾します。
-
schema_names=IF_NEEDEDデフォルト・スキーマに所属しているOUTTYPEファイル内の型名はスキーマ名で修飾しません。デフォルト・スキーマ以外のスキーマに属する型名は、スキーマ名で修飾します。
-
schema_names=FROM_INTYPEintypeファイルに記述されている型は、intypeファイル内のスキーマ名で修飾されている場合にのみ、outtypeファイル内のスキーマ名で修飾されます。デフォルト・スキーマ内の型は、intypeファイル内で記述されていなくても型の依存性によって生成する必要がある場合にはスキーマ名付きで記述されます。これは、その型に依存する型としてOTTで最初に検出された型がスキーマ名付きで記述されていた場合にのみ行われます。ただし、OTTが接続しているデフォルト・スキーマにない型は、常に、明示的に指定したスキーマ名付きで記述されます。
OTT生成のouttypeファイルは、Pro*C/C++に対する入力パラメータです。Pro*C/C++の側から見ると、このファイルはPro*C/C++のintypeファイルです。このファイルは、データベース型名をCの構造体名に対応付けます。この情報は、構造体に対して正しいデータベース型が選択されるように実行時に使用されます。outtypeファイル(Pro*C/C++のintypeファイル)内のスキーマ名で型が指定される場合、その型はプログラムの実行中に名前付きスキーマ内で検出されます。型がスキーマ名なしで指定される場合、その型はプログラムの接続先となるデフォルト・スキーマ内で検出されます。このデフォルト・スキーマは、OTTで使用されたデフォルト・スキーマとは異なる場合があります。
この項には次のトピックが含まれます: 例: Schema_Namesの使用方法。
25.7.6.1 例: Schema_Namesの使用方法
SCHEMA_NAMESパラメータの使用例を示します。
SCHEMA_NAMESにFROM_INTYPEを設定し、次のようにintypeファイルで読み取るとします。
TYPE Person TYPE david.Dept TYPE sam.Company
OTTで生成した構造体を使用して、Pro*C/C++アプリケーションでsam.Company、david.DeptおよびPersonの各型を使用します。スキーマ名のないPersonを使用して、アプリケーションを接続するスキーマのPerson型を表します。
OTTとアプリケーションの両方がスキーマdavidに接続する場合、アプリケーションは、OTTが使用した型と同じ型(david.Person)を使用します。OTTがスキーマdavidに接続し、アプリケーションがスキーマjanaに接続している場合、アプリケーションでは、jana.Person型を使用します。この動作が有効なのは、スキーマdavidとスキーマjanaで同じCREATE TYPE Person文が実行された場合のみです。
一方、アプリケーションでは、どのスキーマに接続するかに関係なくdavid.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がスキーマdavidに接続され、SCHEMA_NAMES=FROM_INTYPEが指定されて、ユーザーのintypeファイルにTYPE PersonまたはTYPE david.Personのいずれかが組み込まれているとします。
ただし、intypeファイルには、david.Person型でネストしたオブジェクト型として使用されているdavid.Address型は記述されていません。intypeファイルにTYPE david.Personが指定されている場合は、TYPE david.PersonとTYPE david.Addressがouttypeファイルに指定されます。intypeファイルにType Personが指定されている場合は、TYPE PersonとTYPE Addressがouttypeファイルに指定されます。
OTTで変換された複数の型にdavid.Address型が埋め込まれていても、intypeファイルに明示的に記述されていない場合、スキーマ名を使用するかどうかは、埋め込まれているdavid.Address型がOTTで最初に検出された時点で決まります。なんらかの理由で、david.Address型にはスキーマ名を付け、一方のPerson型には付けない場合、ユーザーはintypeファイルで明示的に次を指定する必要があります。
TYPE david.Address
各型を単一のスキーマ内に宣言する通常の場合は、すべての型名をintypeファイル内のスキーマ名で修飾するのが最も安全です。
25.7.7 デフォルトの名前のマッピング
OTTでオブジェクト型または属性のC識別子名を作成する場合、OTTは、その名前をデータベース文字セットから有効なC識別子に変換します。
最初に、名前はデータベース文字セットからOTTで使用する文字セットに変換されます。次に、その変換された名前の変換内容がintypeファイルに指定されている場合は、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ファイルで名前の変換を指定する必要があります。
Cの同一の名前に複数のデータベース識別子がマッピングされている場合に生じるネーミングの競合は、OTTでは検出されません。また、データベース識別子がCキーワードにマッピングされるときのネーミング問題も検出されません。
25.7.8 OTTでのファイル名比較の制限事項
現在、OTTは、コマンドラインまたはintypeファイルに指定したファイル名を比較することで、2つのファイルが同一かどうかを判断しています。
OTTで2つのファイル名が同一のファイルを参照しているかどうかを判別する必要がある場合は、1つの潜在的な問題が生じます。たとえば、OTTで生成されたファイルfoo.hで、foo1.hに記述されている型宣言と、/private/elias/foo1.hに記述されている別の型宣言が必要な場合、OTTは、2つのファイルが同一の場合は1つの#includeディレクティブを、異なる場合は2つの#includesディレクティブを生成します。しかし、実際には2つのファイルは異なるという結論が出され、次のように2つの#includesディレクティブが生成されます。
#ifndef FOO1_ORACLE #include "foo1.h" #endif #ifndef FOO1_ORACLE #include "/private/elias/foo1.h" #endif
foo1.hと/private/elias/foo1.hが別々のファイルである場合は、最初のファイルのみが組み込まれます。foo1.hと/private/elias/foo1.hが同一ファイルである場合は、#includeディレクティブが重複して記述されます。
そのため、コマンドラインまたはintypeファイルでファイルを複数回記述するときは、各記述で正確に同じファイル名を使用する必要があります。
25.7.9 Microsoft WindowsでのOTTコマンド
現行リリースにおけるMicrosoft WindowsでのOTT実行可能ファイルは、前回のリリースのott.exeではなく、ott.batです。
ottの実行後、スクリプトがすぐに終了するため、これによってWindowsのバッチ・スクリプトが破棄される可能性があります。この問題を修正するには、Windowsバッチ・スクリプトで、次のようにOTTを起動する必要があります。
call ott [arguments]
ノート:
中間的な解決策として、スクリプトが修正されるまで、ORACLE_HOME\precomp\admin\ott.exeを使用できます。ただし、この中間的な解決策は将来のリリースでは提供されません。
