ヘッダーをスキップ
Oracle® Call Interfaceプログラマーズ・ガイド
11g リリース2 (11.2)
E50264-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

13 ダイレクト・パス・ロード

ダイレクト・パス・ロード関数は、データを外部ファイルから表とパーティションにロードするために使用します。

この章は、次の項目で構成されています。

ダイレクト・パス・ロードの概要

ダイレクト・パス・ロード・インタフェースを使用すると、OCIアプリケーションからOracle Databaseのダイレクト・パス・ロード・エンジンにアクセスし、SQL*Loaderユーティリティの関数を実行できます。この機能によって、データを外部ファイルから表またはパーティション表のパーティションのいずれかにロードできます。

図13-1では、この章のテーマを紹介しています。この図のクライアント側では、データは入力バッファを通して列配列に入力されます。OCIDirPathColArrayToStream()コールにより、データがストリーム形式でサーバー側に移動します。これによりデータが列配列に渡され、この列配列はブロック・フォーマッタを使用して、データをデータベース表に送信します。

図13-1 ダイレクト・パス・ロード

図13-1の説明は次にあります
「図13-1 ダイレクト・パス・ロード」の説明

OCIダイレクト・パス・ロード・インタフェースには、複数行のデータが含まれたダイレクト・パス・ストリームをロードすることによって複数の行をロードできます。

ダイレクト・パスAPIを使用するには、クライアント・アプリケーションで次のステップを実行します。

  1. OCIを初期化します。

  2. ダイレクト・パス・コンテキスト・ハンドルを割り当てて、属性を設定します。

  3. ロードするオブジェクト(表、パーティションまたはサブパーティション)の名前を指定します。

  4. オブジェクトの列の外部データ型を記述します。

  5. ダイレクト・パス・インタフェースを準備します。

  6. 1列以上の列配列を割り当てます。

  7. 1つ以上のダイレクト・パス・ストリームを割り当てます。

  8. 列配列内のエントリを、各列に対する入力データ値を指し示すように設定します。

  9. 列配列をダイレクト・パス・ストリーム形式に変換します。

  10. ダイレクト・パス・ストリームをロードします。

  11. 発生したエラーをすべて取り出します。

  12. ダイレクト・パス終了関数をコールします。

  13. ハンドルおよびデータ構造を解放します。

  14. サーバーから切断します。

ステップ8から11は、ロード対象のデータに従って繰り返すことができます。

ダイレクト・ロード操作では、オブジェクトでDML操作が行われないように、ロード対象のオブジェクトをロックする必要があります。オブジェクトがロードされる間、問合せはロック解除されており、使用可能です。DMLロックのモードおよび取得されるDMLロックは、OCI_ATTR_DIRPATH_PARALLELオプションの仕様、および表全体のロードではなくパーティションまたはサブパーティションのロードが実行されているかどうかに応じて異なります。

  • 表のロードの場合、OCI_ATTR_DIRPATH_PARALLELオプションの設定とその結果は、次のとおりです。

    • FALSEの場合、表DML X-Lockが取得されます。

    • TRUEの場合、表DML S-Lockが取得されます。

  • パーティションのロードの場合、OCI_ATTR_DIRPATH_PARALLELオプションの設定とその結果は、次のとおりです。

    • FALSEの場合、表DML SX-LockとパーティションDML X-Lockが取得されます。

    • TRUEの場合、表DML SS-LockとパーティションDML S-Lockが取得されます。

ダイレクト・パス・ロードでサポートされるデータ型

ダイレクト・パス・ロード操作では、スカラー列に対して有効な外部データ型は次のとおりです。

  • SQLT_CHR

  • SQLT_DAT

  • SQLT_INT

  • SQLT_UIN

  • SQLT_FLT

  • SQLT_BIN

  • SQLT_NUM

  • SQLT_PDN

  • SQLT_CLOB

  • SQLT_BLOB

  • SQLT_DATE

  • SQLT_TIMESTAMP

  • SQLT_TIMESTAMP_TZ

  • SQLT_TIMESTAMP_LTZ

  • SQLT_INTERVAL_YM

  • SQLT_INTERVAL_DS

次の外部オブジェクトのデータ型がサポートされています。

  • SQLT_NTY - 列オブジェクト(FINALNOT FINAL)およびSQL文字列の列

  • SQLT_REF - REF列(FINALNOT FINAL)

次の表の型がサポートされています。

  • ネストした表

  • オブジェクト表(FINALNOT FINAL)


    関連項目:


ダイレクト・パス・ハンドル

ダイレクト・パス・ロードは、ダイレクト・パス配列の挿入操作に対応しています。ダイレクト・パス・ロード・インタフェースでは、次のハンドルを使用してロードされるオブジェクトおよび操作するデータの指定が記録されます。

ダイレクト・パス・コンテキスト

ダイレクト・パス・コンテキスト・ハンドルは、ロード対象の各オブジェクト(表またはパーティション表のパーティションのいずれか)に対して割り当てる必要があります。OCIDirPathCtxハンドルは、OCIDirPathFuncCtxOCIDirPathColArrayおよびOCIDirPathStreamハンドルの親ハンドルであるため、OCIDirPathCtxハンドルを解放すると、その子ハンドルも解放されます(ただし、親ハンドルの解放前に、子ハンドルを個別に解放するコーディングをお薦めします)。

ダイレクト・パス・コンテキストは、OCIHandleAlloc()を使用して割り当てます。ダイレクト・パス・コンテキストの親ハンドルは、常に環境ハンドルです。ダイレクト・パス・コンテキストは、OCIHandleFree()を使用して解放します。例13-1に示すように、すべてのダイレクト・パス・プログラムの最初の2行にヘッダー・ファイルを組み込みます。

例13-1 ヘッダー・ファイルを組み込む必要があるダイレクト・パス・プログラム

...
#include <cdemodp0.h>
#include <cdemodp.h>

OCIEnv *envp;
OCIDirPathCtx *dpctx;
sword error;
error = OCIHandleAlloc((void  *)envp, (void  **)&dpctx,
                    OCI_HTYPE_DIRPATH_CTX, (size_t)0,(void  **)0);
...
error = OCIHandleFree(dpctx, OCI_HTYPE_DIRPATH_CTX);

OCIダイレクト・パス関数コンテキスト


関連項目:

サポートされているデータ型の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。

OCIDirPathFuncCtx型のダイレクト・パス関数コンテキスト・ハンドルは、次の名前付き型とREF列の記述に使用します。

  • 列オブジェクト。このオブジェクト内の関数コンテキストでは、オブジェクト型が記述され、デフォルト・コンストラクタとして使用されて、オブジェクトとそのコンストラクタのオブジェクト属性を作成します。

  • REF列。この列内の関数コンテキストでは、行オブジェクトの参照元である単一のオブジェクト表(オプション)および各行オブジェクトを識別するREF引数が記述されます。

  • SQL文字列の列。この列内の関数コンテキストでは、列にロードする値を計算するためのSQL文字列とその引数が記述されます。

例13-2に示すように、関数コンテキストの割当てを示すには、OCI_HTYPE_DIRPATH_FN_CTXハンドル型をOCIHandleAlloc()に渡します。

例13-2 関数コンテキストを割り当てるためにハンドル型を渡す例

OCIDirPathCtx *dpctx;       /* direct path context */
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
sword error;

error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (size_t)0, (void  **)0);

ダイレクト・パス関数コンテキストの親ハンドルは、常にダイレクト・パス・コンテキスト・ハンドルであることに注意してください。次のOCIHandleFree()を使用して、ダイレクト・パス関数コンテキスト・ハンドルを解放します。

error = OCIHandleFree(dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX);

ダイレクト・パス列配列およびダイレクト・パス関数列配列

ダイレクト・パス・インタフェースに行配列を表示するには、ダイレクト・パス列配列ハンドルおよびダイレクト・パス関数列配列ハンドルを使用します。行は、列の値、列の長さおよび列フラグの3つの配列によって表します。列配列で使用するメソッドには、配列ハンドルの割当て、および配列のエントリに対応する値の設定や取得があります。

これらのハンドルは同じデータ構造体OCIDirPathColArrayを共有しますが、この2つの列配列ハンドルは、親ハンドルとハンドル型が異なります。

ダイレクト・パス列配列ハンドルは、OCIHandleAlloc()を使用して割り当てます。例13-3のコード・フラグメントは、ダイレクト・パス列配列ハンドルの明示的な割当てを示します。

例13-3 ダイレクト・パス列配列ハンドルの明示的な割当て

OCIDirPathCtx *dpctx;      /* direct path context */
OCIDirPathColArray *dpca;  /* direct path column array */
sword error;
error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpca,
               OCI_HTYPE_DIRPATH_COLUMN_ARRAY, 
               (size_t)0, (void  **)0);

ダイレクト・パス列配列ハンドルは、OCIHandleFree()を使用して解放します。

error = OCIHandleFree(dpca, OCI_HTYPE_DIRPATH_COLUMN_ARRAY);

例13-4は、ダイレクト・パス関数列配列ハンドルをほとんど同じ方法で割り当てることを示しています。

例13-4 ダイレクト・パス関数列配列ハンドルの明示的な割当て

OCIDirPathFuncCtx *dpfnctx;   /* direct path function context */
OCIDirPathColArray *dpfnca;   /* direct path function column array */
sword error;
error = OCIHandleAlloc((void  *)dpfnctx, (void  **)&dpfnca,
                        (ub4)OCI_HTYPE_DIRPATH_FN_COL_ARRAY,
                        (size_t)0, (void  **)0);

ダイレクト・パス関数列配列ハンドルは、OCIHandleFree()を使用して解放します。

error = OCIHandleFree(dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY);

OCIDirPathColArrayハンドルの解放により、そのハンドルに関連付けられた列配列も解放されます。

ダイレクト・パス・ストリーム

変換操作OCIDirPathColArrayToStream()およびロード操作OCIDirPathLoadStream()には、ダイレクト・パス・ストリーム・ハンドルを使用します。

ダイレクト・パス・ストリーム・ハンドルは、クライアントがOCIHandleAlloc()を使用して割り当てます。OCIDirPathStreamハンドルの構造体は、フォーム(バッファ、バッファ長)内のペアとみなすことができます。

ダイレクト・パス・ストリームは、Oracle表データの線形表現です。変換操作は、常にストリームの最後に追加されます。ロード操作は、常にストリームの最初に起動します。ストリームのロードが正常終了した後、OCIDirPathStreamReset()をコールしてストリームをリセットする必要があります。

例13-5は、OCIHandleAlloc()を使用して割り当てられるダイレクト・パス・ストリーム・ハンドルを示しています。親ハンドルは、常にOCIDirPathCtxハンドルです。

例13-5 ダイレクト・パス・ストリーム・ハンドルの割当て

OCIDirPathCtx *dpctx;    /* direct path context */
OCIDirPathStream *dpstr; /* direct path stream */
sword error;
error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpstr,
               OCI_HTYPE_DIRPATH_STREAM, (size_t)0,(void  **)0);

ダイレクト・パス・ストリーム・ハンドルは、OCIHandleFree()を使用して解放します。

error = OCIHandleFree(dpstr, OCI_HTYPE_DIRPATH_STREAM);

OCIDirPathStreamハンドルの解放によって、そのハンドルに関連付けられているストリーム・バッファも解放されます。

ダイレクト・パス・インタフェースの関数

この項にリストされた関数は、ダイレクト・パス・ロード・インタフェースとともに使用します。


関連項目:

各関数の詳細は、「ダイレクト・パス・ロード関数」を参照してください。

ダイレクト・パス・コンテキストの操作は、表13-1の関数で実行します。

表13-1 ダイレクト・パス・コンテキストの関数

関数 用途

OCIDirPathAbort()


ダイレクト・パス処理を終了します。

OCIDirPathDataSave()


データのセーブポイントを実行します。

OCIDirPathFinish()


ロードされたデータをコミットします。

OCIDirPathFlushRow()


サーバーから部分的にロードされた行をフラッシュします。この関数は非推奨です。

OCIDirPathLoadStream()


ダイレクト・パス・ストリーム形式に変換されたデータをロードします。

OCIDirPathPrepare()


行の変換またはロードを行うために、ダイレクト・パス・インタフェースを準備します。


ダイレクト・パス列配列の操作は、表13-2の関数で実行します。

表13-2 ダイレクト・パス列配列の関数

関数 用途

OCIDirPathColArrayEntryGet()


列配列内の特定のエントリを取得します。

OCIDirPathColArrayEntrySet()


列配列内の特定のエントリを特定の値に設定します。

OCIDirPathColArrayRowGet()


特定の行番号の基本行ポインタを取得します。

OCIDirPathColArrayReset()


行配列の状態をリセットします。

OCIDirPathColArrayToStream()


列配列形式からダイレクト・パス・ストリーム形式に変換します。


ダイレクト・パス・ストリームの操作は、ダイレクト・ストリームの状態をリセットするOCIDirPathStreamReset()関数で実行します。

ダイレクト・パス・ロード・インタフェースに関する制限と制約

ダイレクト・パス・ロード・インタフェースには、SQL*Loaderと同じ次の制限があります。

  • トリガーがサポートされていません。

  • 参照整合性制約がサポートされていません。

  • クラスタ化表がサポートされていません。

  • リモート・オブジェクトのロードがサポートされていません。

  • LONGは最後に指定してください。

  • LOB、オブジェクトまたはコレクションを戻すSQL文字列がサポートされていません。

  • VARRAY列のロードがサポートされていません。

  • すべてのパーティション列は、LOBの前に指定する必要があります。これは、LOBをパーティションに書き込む前に、書込み先のパーティションを確認する必要があるためです。

スカラー列に対するダイレクト・パス・ロードの例

この項では、スカラー列に対するダイレクト・パス・ロードの例を説明します。

ダイレクト・パス・ロードの例で使用されているデータ構造

例13-6は、例13-7例13-17を介して使用されるデータ構造を示しています。

例13-6 ダイレクト・パス・ロードの例で使用されているデータ構造

/* load control structure */
struct loadctl
{
  ub4                 nrow_ctl;            /* number of rows in column array */
  ub2                 ncol_ctl;         /* number of columns in column array */
  OCIEnv             *envhp_ctl;                       /* environment handle */
  OCIServer          *srvhp_ctl;                            /* server handle */
  OCIError           *errhp_ctl;                             /* error handle */
  OCIError           *errhp2_ctl;                /* yet another error handle */
  OCISvcCtx          *svchp_ctl;                          /* service context */
  OCISession         *authp_ctl;                   /* authentication context */
  OCIParam           *colLstDesc_ctl;        /* column list parameter handle */
  OCIDirPathCtx      *dpctx_ctl;                      /* direct path context */
  OCIDirPathColArray *dpca_ctl;           /* direct path column array handle */
  OCIDirPathColArray *dpobjca_ctl;          /* dp column array handle for obj*/
  OCIDirPathColArray *dpnestedobjca_ctl;  /* dp col array hndl for nested obj*/
  OCIDirPathStream   *dpstr_ctl;                /* direct path stream handle */
  ub1                *buf_ctl;    /* pre-alloc'd buffer for out-of-line data */
  ub4                 bufsz_ctl;                 /* size of buf_ctl in bytes */
  ub4                 bufoff_ctl;                     /* offset into buf_ctl */
  ub4                *otor_ctl;                  /* Offset to Recnum mapping */
  ub1                *inbuf_ctl;                 /* buffer for input records */
  struct pctx         pctx_ctl;                     /* partial field context */
  boolean             loadobjcol_ctl;             /* load to obj col(s)? T/F */
};

例13-7は、複数の構造体を定義するdemoディレクトリのヘッダー・ファイルcdemodp.hを示しています。

例13-7 ヘッダー・ファイルcdemodp.hの内容

#ifndef cdemodp_ORACLE
# define cdemodp_ORACLE

# include <oratypes.h>

# ifndef externdef
#  define externdef
# endif

/* External column attributes */
struct col
{
  text *name_col;                                             /* column name */
  ub2   id_col;                                            /* column load ID */
  ub2   exttyp_col;                                         /* external type */
  text *datemask_col;                             /* datemask, if applicable */
  ub1   prec_col;                                /* precision, if applicable */
  sb1   scale_col;                                   /* scale, if applicable */
  ub2   csid_col;                                        /* character set ID */
  ub1   date_col;            /* is column a chrdate or date? 1=TRUE. 0=FALSE */
  struct obj * obj_col;          /* description of object, if applicable */
#define COL_OID 0x1                                         /* col is an OID */
  ub4   flag_col;
};

/* Input field descriptor
 * For this example (and simplicity),
 * fields are strictly positional.
 */
struct fld
{
  ub4  begpos_fld;                             /* 1-based beginning position */
  ub4  endpos_fld;                             /* 1-based ending    position */
  ub4  maxlen_fld;                       /* max length for out-of-line field */
  ub4    flag_fld;
#define FLD_INLINE            0x1
#define FLD_OUTOFLINE         0x2
#define FLD_STRIP_LEAD_BLANK  0x4
#define FLD_STRIP_TRAIL_BLANK 0x8
};

struct obj
{
  text               *name_obj;                                /* type  name*/
  ub2                 ncol_obj;              /* number of columns in col_obj*/
  struct col         *col_obj;                          /* column attributes*/
  struct fld         *fld_obj;                           /* field descriptor*/
  ub4                 rowoff_obj;  /* current row offset in the column array*/
  ub4                 nrows_obj;              /* number of rows in col array*/
  OCIDirPathFuncCtx  *ctx_obj;       /* Function context for this obj column*/
  OCIDirPathColArray *ca_obj;           /* column array  for this obj column*/
  ub4                 flag_obj;                              /* type of obj */
#define OBJ_OBJ  0x1                                             /* obj col */
#define OBJ_OPQ  0x2                                  /* opaque/sql str col */
#define OBJ_REF  0x4                                             /* ref col */
};

struct tbl
{
  text        *owner_tbl;                                     /* table owner */
  text        *name_tbl;                                       /* table name */
  text        *subname_tbl;                        /* subname, if applicable */
  ub2          ncol_tbl;                     /* number of columns in col_tbl */
  text        *dfltdatemask_tbl;            /* table level default date mask */
  struct col  *col_tbl;                                 /* column attributes */
  struct fld  *fld_tbl;                                  /* field descriptor */
  ub1          parallel_tbl;                         /* parallel: 1 for true */
  ub1          nolog_tbl;                          /* no logging: 1 for true */
  ub4          xfrsz_tbl;                   /* transfer buffer size in bytes */
  text         *objconstr_tbl;   /* obj constr/type if loading a derived obj */
};

struct sess                        /* options for a direct path load session */
{
  text        *username_sess;                                        /* user */
  text        *password_sess;                                    /* password */
  text        *inst_sess;                            /* remote instance name */
  text        *outfn_sess;                                /* output filename */
  ub4          maxreclen_sess;          /* max size of input record in bytes */
};
#endif                                              /* cdemodp_ORACLE */

スカラー列に対するダイレクト・パス・ロードの例の概略

例13-8は、OCIダイレクト・パス・インタフェースの使用方法の例を示すサンプル・コードです。これは一部省略されたコード例です。

init_load関数は、tblpで記述された表上で、ダイレクト・パスAPIを使用してダイレクト・パス・ロードを実行します。ctlpによって指定されたloadctl構造体の環境およびサービス・コンテキストは、適切に初期化されています。サーバーへの接続は確立されています。

例13-8 OCIダイレクト・パス・インタフェースの使用方法

STATICF void
init_load(ctlp, tblp)
struct loadctl *ctlp;
struct tbl     *tblp;
{
  struct  col   *colp;
  struct  fld   *fldp;
  sword          ociret;                       /* return code from OCI calls */
  OCIDirPathCtx *dpctx;                               /* direct path context */
  OCIParam      *colDesc;                     /* column parameter descriptor */
  ub1            parmtyp;
  ub1           *timestamp = (ub1 *)0;
  ub4            size;
  ub4            i;
  ub4            pos;

  /* allocate and initialize a direct path context */
  /* See cdemodp.c for the definition of OCI_CHECK */
  OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp,
            OCIHandleAlloc((void  *)ctlp->envhp_ctl,
                           (void  **)&ctlp->dpctx_ctl,
                           (ub4)OCI_HTYPE_DIRPATH_CTX,
                           (size_t)0, (void  **)0));

  dpctx = ctlp->dpctx_ctl;                                      /* shorthand */

  OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
            OCIAttrSet((void  *)dpctx, (ub4)OCI_HTYPE_DIRPATH_CTX,
                       (void  *)tblp->name_tbl,
                       (ub4)strlen((const char *)tblp->name_tbl),
                       (ub4)OCI_ATTR_NAME, ctlp->errhp_ctl));

OCI_ATTR_SUB_NAMEOCI_ATTR_SCHEMA_NAMEなど、その他の属性も設定します。属性を設定した後、ロードの準備をします。

  OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
            OCIDirPathPrepare(dpctx, ctlp->svchp_ctl, ctlp->errhp_ctl));

列配列とストリーム・ハンドルの割当て

例13-9に示すように、ダイレクト・パス・コンテキスト・ハンドルは、列配列ハンドルおよびストリーム・ハンドルの親ハンドルです。また、エラーは、ダイレクト・パス・コンテキストに関連付けられている環境ハンドルとともに戻されます。

例13-9 列配列とストリーム・ハンドルの割当て

   OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp,
            OCIHandleAlloc((void  *)ctlp->dpctx_ctl, (void  **)&ctlp->dpca_ctl,
                           (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY,
                           (size_t)0, (void  **)0));

  OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp,
            OCIHandleAlloc((void  *)ctlp->dpctx_ctl,(void  **)&ctlp->dpstr_ctl,
                           (ub4)OCI_HTYPE_DIRPATH_STREAM,
                           (size_t)0, (void  **)0));

行数と列数の取得

例13-10に示すように、割り当てた列配列から行数および列数を取得します。

例13-10 行数と列数の取得

  OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
            OCIAttrGet(ctlp->dpca_ctl, (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY,
                       &ctlp->nrow_ctl, 0, OCI_ATTR_NUM_ROWS,
                       ctlp->errhp_ctl));

   OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
            OCIAttrGet(ctlp->dpca_ctl, (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY,
                       &ctlp->ncol_ctl, 0, OCI_ATTR_NUM_COLS,
                       ctlp->errhp_ctl));

入力データ・フィールドの設定

例13-11に示すように、入力データ・フィールドを対応するデータ列に設定します。

例13-11 入力データ・フィールドの設定

ub4            rowoff;                          /* column array row offset */
ub4            clen;                                      /* column length */
ub1            cflg;                                  /* column state flag */
ub1           *cval;                             /* column character value */

OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
            OCIDirPathColArrayEntrySet(ctlp->dpca_ctl, ctlp->errhp_ctl,
                                       rowoff, colp->id_col,
                                       cval, clen, cflg));

列配列の状態のリセット

例13-12に示すように、前の変換を続ける必要がある場合、または行にデータを追加する場合は、列配列の状態をリセットします。

例13-12 列配列の状態のリセット

(void) OCIDirPathColArrayReset(ctlp->dpca_ctl, ctlp->errhp_ctl);

ストリームの状態のリセット

例13-13に示すように、ストリームの状態をリセットして、新しいストリームを開始します。リセットしなかった場合は、ストリーム内のデータが既存のデータの末尾に追加されます。

例13-13 ストリームの状態のリセット

(void) OCIDirPathStreamReset(ctlp->dpstr_ctl, ctlp->errhp_ctl);

列配列内のデータのストリーム形式への変換

例13-14に示すように、データの入力後、列配列内のデータをストリーム形式に変換し、不正なレコードを削除します。

例13-14 データのストリーム形式への変換

ub4            rowcnt;                   /* number of rows in column array */
ub4            startoff;         /* starting row offset into column array  */

/* convert array to stream, filter out bad records */
ocierr = OCIDirPathColArrayToStream(ctlp->dpca_ctl, ctlp->dpctx_ctl,
                                        ctlp->dpstr_ctl, ctlp->errhp_ctl,
                                        rowcnt, startoff);

ストリームのロード

ストリーム内での位置は、ストリームを作成した列配列のオフセット情報とともに、ストリーム・ハンドルに内部的に保持されます。例13-15に示すように、ストリーム形式への変換が実行されると、ストリームにデータが追加されます。適切な場合にストリームをリセットすることはコール元の責任です。エラーが発生すると、位置は次の行に移動します。エラーが最後の行で発生した場合は、ストリームの最後に移動します。次のOCIDirPathLoadStream()コールがある場合は、次の行で開始されます。OCIDirPathLoadStream()コールが実行され、ストリームの最後に達した場合は、OCI_NO_DATAが戻されます。

例13-15 ストリームのロード

/* load the stream */
ociret = OCIDirPathLoadStream(ctlp->dpctx_ctl, ctlp->dpstr_ctl,
            ctlp->errhp_ctl);

ダイレクト・パス・ロードの終了

例13-16に示すように、ダイレクト・パス・ロードを終了します。

例13-16 ダイレクト・パス・ロード操作の終了

/* finish the direct path load operation */
OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp,
          OCIDirPathFinish(ctlp->dpctx_ctl, ctlp->errhp_ctl));

ダイレクト・パス・ハンドルの解放

例13-17に示すように、割り当てられているすべてのダイレクト・パス・ハンドルを解放します。親のダイレクト・パス・コンテキスト・ハンドルの解放前に、ダイレクト・パス列配列ハンドルとストリーム・ハンドルが解放されます。

例13-17 ダイレクト・パス・ハンドルの解放

/* free up server data structures for the load */
ociret = OCIHandleFree((void  *)ctlp->dpca_ctl,
                           OCI_HTYPE_DIRPATH_COLUMN_ARRAY);
ociret = OCIHandleFree((void  *)ctlp->dpstr_ctl,
                           OCI_HTYPE_DIRPATH_STREAM);
ociret = OCIHandleFree((void  *)ctlp->dpctx_ctl, 
                          OCI_HTYPE_DIRPATH_CTX);

OCIのダイレクト・パス・ロードでの日付キャッシュの使用

表に格納するためにデータ型変換が必要なOracle日付およびタイムスタンプの値をロードする場合は、日付キャッシュ機能を使用するとパフォーマンスが向上します。ダイレクト・パス・ロードでのこの機能の使用方法の詳細は、『Oracle Databaseユーティリティ』を参照してください。

この機能は、同じ日付またはタイムスタンプの値が入力値として繰返しロードされるダイレクト・パス・ロードを特に対象としています。日付変換は(特に複数の日付列がロードされる場合)、非常に時間がかかり、ロード時間の中で大きな割合を占める場合があります。入力データに多数の同じ日付値がある場合は、日付キャッシュ機能を使用すると実際に変換される日付の数が減少するため、パフォーマンスが向上します。ただし、日付キャッシュ機能によってパフォーマンスが向上するのは、多数の同じ日付が入力値として日付列にロードされる場合のみです(この章で使用する「日付」という用語は、日付およびタイムスタンプのすべてのデータ型を指します)。

日付キャッシュはデフォルトで有効です。日付キャッシュ・サイズを明示的に指定した場合、デフォルトでは日付キャッシュ機能は使用禁止になりません。この動作をオーバーライドするには、OCI_ATTR_DIRPATH_DCACHE_DISABLEを1に設定します。この設定以外の場合は、データ変換を回避するためにキャッシュが検索されます。ただし、キャッシュ・ミス(重複した値がないエントリ)は、日付キャッシュ機能の使用による効果がなく、時間がかかる日付変換関数を使用した通常の方法で変換されます。

OCI_ATTR_DIRPATH_DCACHE_NUM属性、OCI_ATTR_DIRPATH_DCACHE_MISSES属性およびOCI_ATTR_DIRPATH_DCACHE_HITS属性を問い合せて、ロードに必要なキャッシュ・サイズを調整します。

キャッシュ・ミスがなく、キャッシュ内の要素数がキャッシュ・サイズより小さい場合は、キャッシュ・サイズを小さくします。多数のキャッシュ・ミスが発生し、相対的にヒット数(重複した値があるエントリ)が少ない場合は、キャッシュ・サイズを大きくすることができます。ただし、多数の日付キャッシュ・ミスが発生すると、アプリケーションの処理速度は日付キャッシュを使用しない場合よりも遅くなる場合があります。キャッシュ・サイズを大きくしすぎると、ページングやメモリー消費量の増加など、別の問題が発生する可能性があります。キャッシュ・サイズを大きくしてもパフォーマンスが向上しない場合、この機能は使用しないでください。

日付キャッシュ機能を明示的かつ全体的に使用禁止にするには、日付キャッシュ・サイズを0 (ゼロ)に設定します。

この機能では、次のOCIダイレクト・パス・コンテキスト属性を設定できます。

OCI_ATTR_DIRPATH_DCACHE_SIZE

この属性を0 (ゼロ)以外に設定する場合は、表に対する日付キャッシュ・サイズを要素数で設定します。たとえば、日付キャッシュ・サイズを200に設定すると、最大200個の一意の日付またはタイムスタンプ値をキャッシュに格納できます。OCIDirPathPrepare()をコールした後は、日付キャッシュ・サイズを変更できません。デフォルト値は0 (ゼロ)で、これは表に対する日付キャッシュが作成されないことを意味します。日付キャッシュは、データ型変換が必要な1つ以上の日付またはタイムスタンプ値がロードされ、この属性値が0 (ゼロ)以外の場合のみ、表に対して作成されます。

OCI_ATTR_DIRPATH_DCACHE_NUM

この属性を使用して、日付キャッシュ内の現在のエントリ数を問い合せます。

OCI_ATTR_DIRPATH_DCACHE_MISSES

この属性を使用して、現在の日付キャッシュ・ミス数を問い合せます。ミスの数が多い場合は、より大きい日付キャッシュ・サイズを使用することを検討してください。日付キャッシュ・サイズを大きくしてもこの数が大幅に減少しない場合は、日付キャッシュ機能を使用しないでください。日付キャッシュ・ミスが発生すると、ハッシングや参照のために時間を費やします。

OCI_ATTR_DIRPATH_DCACHE_HITS

この属性を使用して、日付キャッシュ・ヒット数を問い合せます。日付キャッシュ機能の使用による効果があることを確認するには、この数が相対的に多くなる必要があります。

OCI_ATTR_DIRPATH_DCACHE_DISABLE

この属性を1に設定すると、サイズを超えた場合に日付キャッシュが使用禁止になります。OCIDirPathPrepare()をコールした後は、この属性を変更または設定できません。

デフォルト(= 0)では、オーバーフロー時にキャッシュが使用禁止になりません。キャッシュが使用禁止でない場合は、変換を回避するためにキャッシュが検索されますが、入力された日付値のエントリがオーバーフローすると日付キャッシュには追加されず、時間がかかる日付変換関数を使用して変換されます。多数の日付キャッシュ・ミスが発生すると、アプリケーションの処理速度は日付キャッシュを使用しない場合よりも遅くなる場合があります。

この属性を問い合せると、オーバーフローが原因で日付キャッシュが使用禁止になっているかどうかも確認できます。

オブジェクト型のダイレクト・パス・ロード

この項では、ダイレクト・パス関数コンテキストによる多様な非スカラー型のロードについて説明します。

非スカラー型は、次のとおりです。

  • ネストした表

  • オブジェクト表(FINALNOT FINAL)

  • 列オブジェクト(FINALNOT FINAL)

  • REF列(FINALNOT FINAL)

  • SQL文字列の列


    関連項目:

    Oracle Databaseのインストールで使用可能なダイレクト・パス・ロードのデモ・プログラムのリストは、表B-1を参照してください。

ネストした表のダイレクト・パス・ロード

ネストした表は、別の表に格納されます。ダイレクト・パス・ロードAPIを使用して、ネストした表をSETIDという外部キーで、その親の表とは別にロードし、2つの表をリンクします。


注意:

  • 現在、SETIDはシステムで生成されないため、ユーザーによる指定が必要です。

  • 親と子の表を別々にロードするときに、子の表に行は挿入されているが、対応する親の行が親の表に挿入されていない場合、孤立した子が作成される可能性があります。また、親の表には親の行が挿入されているが、子の表には子の行が挿入されていない場合、親の行において子が欠落します。


ネストした表の列とそのネストした表の記述


注意:

スカラー・データのロードと異なるステップは、イタリック表記になっています。

ネストした表の列を持つ親表のロードと、子であるネストした表のロードは、別のアクションです。

  • ネストした表の列を持つ親表をロードする手順は、次のとおりです。

    1. 親表とその列を通常どおり記述しますが、このとき、次の手順を行います。

    2. ネストした表の列を記述するときに、この列にSETIDを格納します。外部データ型は、データ・ファイルのSETIDが文字の場合はSQLT_CHRで、バイナリの場合はSQLT_BINです。

  • ネストした表(子)をロードする手順は、次のとおりです。

    1. ネストした表とその列を通常どおり記述します。

    2. SETID 列は必須です。

      • ダミーの名前(setidなど)を使用して、そのOCI_ATTR_NAMEを設定します。これは、APIでは、プログラマがそのシステム名を認識しているとはみなしていないためです。

      • これがSETID列であることを示すように、OCI_ATTR_DIRPATH_SIDで列属性を設定します。

        ub1 flg = 1;
        sword error;
        
        error = OCIAttrSet((void  *)colDesc,
                           OCI_DTYPE_PARAM,
                           (void  *)&flg, (ub4)0,
                           OCI_ATTR_DIRPATH_SID, ctlp->errhp_ctl);
        

列オブジェクトのダイレクト・パス・ロード

列オブジェクトとは、オブジェクトとして定義される表の列のことです。現在は、すべての構成属性で構成されるデフォルト・コンストラクタのみがサポートされています。

列オブジェクトの記述

列オブジェクトとそのオブジェクト属性を記述するには、ダイレクト・パス関数コンテキストを使用します。列オブジェクトの記述には、そのオブジェクトのコンストラクタの設定が必要です。オブジェクト属性の記述は、スカラー列のリストの記述に類似しています。

列オブジェクトを記述する手順は、次のとおりです。


注意:

  • ネストした列のオブジェクトがサポートされています。

  • 次に説明する手順は、表にロードするスカラー列のリストを記述する手順に類似しています。スカラー・データのロードと異なるステップは、イタリック表記になっています。


  1. パラメータ・ハンドルをOCI_DTYPE_PARAMで列オブジェクトに割り当てます。このパラメータ・ハンドルを使用して、列の外部属性を設定します。

  2. 列名とその他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

  3. OCI_ATTR_DATA_TYPEで、外部型をSQLT_NTY (名前付き型)として設定します。

  4. ダイレクト・パス関数コンテキスト・ハンドルを割り当てます。このコンテキストを使用して、列のオブジェクト型と属性を記述します。

    OCIDirPathFuncCtx *dpfnctx  /* direct path function context */;
    sword error;
    error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpfnctx,
                   OCI_HTYPE_DIRPATH_FN_CTX, 
                   (size_t)0, (void  **)0);
    
  5. 関数コンテキストのOCI_ATTR_NAMEで列のオブジェクト型の名前(Employeeなど)を設定します。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    text *obj_type;   /* column object's object type */
    sword error;
    
    error = OCIAttrSet((void  *)dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (void  *)obj_type, (ub4)strlen((const char *)obj_type),
                       OCI_ATTR_NAME, ctlp->errhp_ctl);
    
  6. 式の型OCI_ATTR_DIRPATH_EXPR_TYPEをOCI_DIRPATH_EXPR_OBJ_CONSTRに設定します。これは、OCI_ATTR_NAMEを持つ式セットが、デフォルトのオブジェクト・コンストラクタとして使用されることを意味します。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    ub1 expr_type = OCI_DIRPATH_EXPR_OBJ_CONSTR;
    sword error;
    
    error = OCIAttrSet((void  *)dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (void  *)&expr_type, (ub4)0,
                       OCI_ATTR_DIRPATH_EXPR_TYPE,
                       ctlp->errhp_ctl);
    
  7. OCI_ATTR_NUM_COLSを使用して、この列オブジェクトにロードする列またはオブジェクト属性の数を設定します。

  8. 関数コンテキストOCIDirPathFuncCtxの列または属性のパラメータ・リストを取得します。

  9. 各オブジェクト属性の場合:

    1. OCI_DTYPE_PARAMで、オブジェクト属性の列記述子を取得します。

    2. OCI_ATTR_NAMEで属性の列名を設定します。

    3. OCI_ATTR_DATA_TYPEで外部列の型(ダイレクト・パスAPIに渡されるデータの型)を設定します。

    4. その他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

    5. この属性の列が列オブジェクトの場合は、そのオブジェクト属性に対して手順3から10を実行します。

    6. 列記述子へのハンドルを解放します。

  10. 手順4で作成した関数コンテキストOCIDirPathFuncCtxを、親の列オブジェクトのパラメータ・ハンドルにOCI_ATTR_DIRPATH_FN_CTXを使用して設定します。

列配列の列オブジェクトへの割当て

列オブジェクトをダイレクト・パス・ロードすると、そのオブジェクトの属性データは、そのオブジェクト専用に作成された個別の列配列にロードされます。子の列配列は、ネストされているかどうかに関係なく、各列オブジェクトに割り当てられます。子の列配列にあるオブジェクト属性の各行は、その親列配列内の親の列オブジェクトにある対応するNULL以外の行にマップされます。

列オブジェクトのダイレクト・パス関数コンテキスト・ハンドルとOCI_HTYPE_DIRPATH_FN_COL_ARRAY関数列配列値を使用します。

例13-18は、列オブジェクトに子の列配列を割り当てる方法を示しています。

例13-18 列オブジェクトへの子の列配列の割当て

OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
OCIDirPathColArray *dpfnca;   /* direct path function column array */
sword error;

error = OCIHandleAlloc((void  *)dpfnctx, (void  **)&dpfnca,
                       OCI_HTYPE_DIRPATH_FN_COL_ARRAY,
                       (size_t)0, (void  **)0);

列オブジェクト・データの列配列へのロード

列がスカラー列の場合は、その値のアドレスをOCIDirPathColArrayEntrySet()に渡して、その値を列配列に設定します。列がオブジェクトの場合は、かわりに、子の列配列ハンドルのアドレスを渡します。子の列配列にはオブジェクトの属性データが格納されます。

データを列オブジェクトにロードする手順は、次のとおりです。


注意:

スカラー・データのロードと異なるステップは、イタリック表記になっています。

(開始します。)各列オブジェクトに対して、次の手順を実行します。

  1. 列がNULL以外の場合:

    1. オブジェクト属性の列ごとに、次の操作を行います。

      オブジェクト属性がネストされた列オブジェクトの場合は、(開始)に移動し、この全手順を繰り返し実行します。

      OCIDirPathColArrayEntrySet()を使用して、子列配列にデータを設定します。

    2. 子列配列ハンドルのアドレスをOCIDirPathColArrayEntrySet()に渡すことにより、列配列で列オブジェクトのデータを設定します。

  2. 列がNULLの場合:

    データのNULLアドレス、長さ0 (ゼロ)およびOCI_DIRPATH_COL_NULLフラグをOCIDirPathColArrayEntrySet()に渡して、列オブジェクトのデータを列配列に設定します。

OCI_DIRPATH_COL_ERROR

OCI_DIRPATH_COL_ERRORの値をOCIDirPathColArrayEntry()に渡すことにより、現在の列配列行を無視する必要があることを示します。一部の列にデータを追加するときにエラーが発生した場合(前のOCIDirPathColArrayToStream()コールからOCI_NEED_DATAが戻された場合)は、通常、この値を使用して前のすべての行変換を取り消します。現在の行の出力ストリーム・バッファに格納されている、前に変換されたデータは削除されます。これにより、変換は列配列内の次の行から続行されます。削除された行は、変換された行としてカウントされます。

OCI_DIRPATH_COL_ERRORを指定すると、現在の行の他、参照される子列配列で対応する任意の行(最上位レベルの列配列行までの行)が無視されます。参照されるすべての子列配列を次の行に移動すると、NULL子列配列参照は無視されます。

SQL文字列の列のダイレクト・パス・ロード

列の値は、SQL文字列で計算できます。SQL文字列は、スカラー列の型に使用できます。SQL文字列は、オブジェクト型には使用できませんが、スカラー列の型のオブジェクト属性には使用できます。NESTED TABLE、SEQUENCEおよびLONGには使用できません。

SQL式は、OCIDirPathFuncCtxを使用してダイレクト・パスAPIで表現します。式のOCI_ATTR_NAMEの値が、その式の名前付きバインド変数のパラメータ・リストを含むSQL文字列になります。

バインド変数のネームスペースは、列のSQL文字列に限定されています。複数の列に対して同じバインド変数名を使用できますが、同じ名前の引数はその列のSQL文字列に対してのみ適用されます。

列のSQL文字列に1つのバインド変数への複数の参照が含まれており、その名前で複数の引数が指定されている場合は、すべての値を同じにする必要があります。同じにしない場合、結果が未定義になります。この場合、特定のSQL式内の同じバインド変数名への参照がすべて1つの引数にバインドされているため、実際に必要なのは1つの引数のみです。

SQL文字列の例を、次に示します。

substr(substr(:string, :offset, :length), :offset, :length)

この例では、次の点に注意してください。

  • SQL式はネストできます。

  • バインド変数名は、その式内で繰り返し指定できます。

SQL文字列の列の記述


注意:

スカラー・データのロードと異なるステップは、イタリック表記になっています。

  1. パラメータ・ハンドルをOCI_DTYPE_PARAMでSQL文字列の列に割り当てます。このパラメータ・ハンドルを使用して、列の外部属性を設定します。

  2. 列名とその他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

  3. OCI_ATTR_DATA_TYPEを使用して、SQL文字列の列の外部型をSQLT_NTYとして設定します。

  4. ダイレクト・パス関数コンテキスト・ハンドルを割り当てます。このコンテキストを使用して、SQL文字列の引数を記述します。

    OCIDirPathFuncCtx *dpfnctx  /* direct path function context */;
    sword error;
    error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpfnctx,
                   OCI_HTYPE_DIRPATH_FN_CTX, 
                   (size_t)0, (void  **)0);
    
  5. 列のSQL文字列を関数コンテキストのOCI_ATTR_NAMEに設定します。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    text *sql_str;   /* column's SQL string expression */
    sword error;
    
    error = OCIAttrSet((void  *)dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (void  *)sql_str, (ub4)strlen((const char *)sql_str),
                       OCI_ATTR_NAME, ctlp->errhp_ctl);
    
  6. 式の型OCI_ATTR_DIRPATH_EXPR_TYPEをOCI_DIRPATH_EXPR_SQLとして設定します。これは、OCI_ATTR_NAMEを持つ式セットが、値を導出するためのSQL文字列として使用されることを意味します。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    ub1 expr_type = OCI_DIRPATH_EXPR_SQL;
    sword error;
    
    error = OCIAttrSet((void  *)dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (void  *)&expr_type, (ub4)0,
                       OCI_ATTR_DIRPATH_EXPR_TYPE, ctlp->errhp_ctl);
    
  7. SQL文字列に渡す引数の数をOCI_ATTR_NUM_COLSを使用して設定します。

  8. 関数コンテキストの列または属性のパラメータ・リストを取得します。

  9. SQL文字列の引数ごとに、次の操作を行います。

    1. OCI_DTYPE_PARAMで、オブジェクト属性の列記述子を取得します。

    2. SQL文字列の引数の定義順序は重要ではありません。SQL文字列で使用されている順序と一致させる必要はありません。

    3. OCI_ATTR_NAMEで属性の列名を設定します。

    4. SQL文字列の引数には、ネーミング規則が適用されます。

    5. 引数名は、SQL文字列で使用されているバインド変数名と内容が一致している必要がありますが、大/小文字区別を一致させる必要はありません。たとえば、SQL文字列がsubstr(:INPUT_STRING, 3, 5)の場合は、引数名をinput_stringにしてもかまいません。

    6. 1つの引数をSQL文字列内で繰り返し使用する場合は、宣言は1回のみ実施し、1つの引数としてのみカウントしてください。

    7. OCI_ATTR_DATA_TYPEで外部列の型(ダイレクト・パスAPIに渡されるデータの型)を設定します。

    8. その他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

    9. 列記述子へのハンドルを解放します。

  10. 手順4で作成した関数コンテキストOCIDirPathFuncCtxを、親の列オブジェクトのパラメータ・ハンドルにOCI_ATTR_DIRPATH_FN_CTXを使用して設定します。

列配列のSQL文字列の列への割当て

SQL文字列の列をダイレクト・パス・ロードすると、その引数のデータは、そのSQL文字列の列専用に作成された個別の列配列にロードされます。子の列配列は、SQL文字列の列ごとに割り当てられます。子の列配列にある引数の各行は、その親列配列内の親のSQL文字列の列にある対応するNULL以外の行にマップされます。

例13-19は、SQL文字列の列に子の列配列を割り当てる方法を示しています。

例13-19 SQL文字列の列への子の列配列の割当て

OCIDirPathFuncCtx *dpfnctx;        /* direct path function context */
OCIDirPathColArray *dpfnca;   /* direct path function column array */
sword error;

error = OCIHandleAlloc((void  *)dpfnctx, (void  **)&dpfnca, 
                       OCI_HTYPE_DIRPATH_FN_COL_ARRAY,
                       (size_t)0, (void  **)0);

SQL文字列データの列配列へのロード

列がスカラー列の場合は、その値のアドレスをOCIDirPathColArrayEntrySet()に渡して、その値を列配列に設定します。列がSQL文字列型の場合は、かわりに、子の列配列ハンドルのアドレスを渡します。子の列配列には、SQL文字列の引数データが格納されます。

データをSQL文字列の列にロードする手順は、次のとおりです。


注意:

スカラー・データのロードと異なるステップは、イタリック表記になっています。

SQL文字列の列ごとに、次の操作を行います。

  1. 列がNULL以外の場合:

    1. 関数の引数の列ごとに、次の操作を行います。

      OCIDirPathColArrayEntrySet()を使用して、子列配列にデータを設定します。

    2. 子列配列ハンドルのアドレスをOCIDirPathColArrayEntrySet()に渡すことにより、SQL文字列の列データを列配列に設定します。

  2. 列がNULLの場合:

    データのNULLアドレス、長さ0 (ゼロ)およびOCI_DIRPATH_COL_NULLフラグをOCIDirPathColArrayEntrySet()に渡して、SQL文字列の列データを列配列に設定します。

この処理は、列オブジェクトの処理に類似しています。


関連項目:

OCI_DIRPATH_COL_ERRORの値をOCIDirPathColArrayEntry()に渡して、エラー発生時に現在の列配列行を無視する必要があることを示す方法の詳細は、「OCI_DIRPATH_COL_ERROR」を参照してください。

REF列のダイレクト・パス・ロード

REF型とは、オブジェクト表の行オブジェクトへのポインタ、つまり参照です。

REF列の記述

REF列への引数の記述は、表にロードする列リストの記述に類似しています。


注意:

REF列は、表のトップレベル列に設定したり、オブジェクト属性として列オブジェクトにネストできます。

スカラー・データのロードと異なるステップは、イタリック表記になっています。


  1. OCI_DTYPE_PARAMで、REF列のパラメータ・ハンドルを取得します。このパラメータ・ハンドルを使用して、列の外部属性を設定します。

  2. 列名とその他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

  3. OCI_ATTR_DATA_TYPEを使用して、REF列の外部型をSQLT_REFとして設定します。

  4. ダイレクト・パス関数コンテキスト・ハンドルを割り当てます。このコンテキストを使用して、REF列の引数を記述します。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    sword error;
    
    error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpfnctx,
                           OCI_HTYPE_DIRPATH_FN_CTX,
                           (size_t)0, (void  **)0);
    
  5. オプション: REF列の表名を関数コンテキストのOCI_ATTR_NAMEに設定します。詳細は、次の手順を参照してください。

    OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
    text *ref_tbl;     /* column's reference table */
    sword error;
    
    error = OCIAttrSet((void  *)dpfnctx,
                       OCI_HTYPE_DIRPATH_FN_CTX,
                       (void  *)ref_tbl, (ub4)strlen((const char *)ref_tbl),
                       OCI_ATTR_NAME, ctlp->errhp_ctl);
    
  6. オプション: 式の型OCI_ATTR_DIRPATH_EXPR_TYPEをOCI_DIRPATH_EXPR_REF_TBLNAMEに設定します。この設定は、手順5が完了している場合にのみ実行します。これは、OCI_ATTR_NAMEを持つ式セットが、行オブジェクトを参照するためのオブジェクト表として使用されることを意味します。このパラメータはオプションです。このパラメータの動作は、REFの型によって異なります。

    • 有効範囲なしのREF列(有効範囲なし、システムOIDベース)

      このパラメータが設定されていない場合、このREF列には、有効範囲なしのREF列の定義により、参照表の名前が引数としてデータ行ごとに含まれている必要があります。

      パラメータが設定されている場合、このREF列がロードの継続時間中に参照できるのは、指定されたオブジェクト表の行オブジェクトのみです。このREF列に、参照表の名前を引数として含めることはできません。(ダイレクト・パスAPIは、このパラメータをショート・カットとしてユーザーに提供しています。ユーザーは、このパラメータをロードの継続時間中に同じ参照オブジェクト表を参照する有効範囲なしのREF列にロードします)。

    • 有効範囲付REF列(有効範囲付、システムOIDベースおよび主キー・ベース)

      このパラメータが設定されていない場合、ダイレクト・パスAPIは、スキーマで指定されている参照表を使用します。

      設定されている場合、参照表の名前は、この有効範囲付REF列のスキーマに指定されているオブジェクト表と一致している必要があります。表名が一致していない場合は、エラーが発生します。

      このパラメータが設定されているかどうかに関係なく、この参照表の名前がデータ行に存在しているかどうかはAPIにとって問題ではありません。名前がデータ行にある場合、その名前はスキーマに指定されている表名と一致している必要があります。名前がデータ行にない場合、APIはスキーマに指定されている参照表を使用します。

  7. 行オブジェクトの参照に使用するREF引数の数を、OCI_ATTR_NUM_COLSで設定します。必要な引数の数は、REF列の型によって異なります。この数は、前述の手順6で導出されます。

    • 有効範囲なしのREF列(有効範囲なし、システムOIDベースのREF列)

      OCI_DIRPATH_EXPR_REF_TBLNAMEが使用されている場合は、1つの引数が導出されます。参照表の名前の引数はなく、OID値の引数が1つです。

      OCI_DIRPATH_EXPR_REF_TBLNAMEが使用されていない場合は、2つです。参照表の名前の引数が1つとOID値の引数が1つです。

    • 有効範囲付REF列(有効範囲付、システムOIDベースおよび主キー・ベース)

      OCI_DIRPATH_EXPR_REF_TBLNAMEを使用しているかどうかにかかわらず、オブジェクトIDを構成している列数がNの場合、受入れ可能な数はNまたはN+1です。参照表の名前がデータ行にない場合、最小値はNです。参照表の名前がデータ行にある場合、その最小値はN+1です。注意: REFがシステムOIDベースの場合、Nは1になります。REFが主キー・ベースの場合、Nは主キーを構成するコンポーネント列の数になります。参照表の名前がデータ行にある場合は、Nに1を加算します。


      注意:

      NまたはN+1以外のある数のREF引数で渡された場合のエラー・メッセージを簡単化するには、Nを予期している際に何らかの数の引数が検出されたことだけを示すエラー・メッセージにします。メッセージではN+1について記述されていませんが、N+1は受入れ可能である(参照表名が必要ない場合でも)ため、エラー・メッセージは表示されません。

  8. 関数コンテキストの列または属性のパラメータ・リストを取得します。

  9. REFの引数または属性ごとに、次の操作を行います。

    1. OCI_DTYPE_PARAMで、REF引数の列記述子を取得します。

    2. OCI_ATTR_NAMEで属性の列名を設定します。

      REF引数の順序は重要です。参照表の名前が指定されている場合は、その名前を最初のREF引数に指定します。オブジェクトIDは、システム生成または主キー・ベースに関係なく、次のREF引数に指定します。

      REF引数には次のネーミング規則が適用されます。参照表の名前は表の列ではないため、列名にref-tblなどのダミーの名前を使用できます。システム生成のOID列に対しては、列名にsys-OIDなどのダミーの名前を使用できます。主キー・ベースのオブジェクトIDに対しては、ロード対象のすべての主キー列をリストします。OIDに対してダミーの名前を作成する必要はありません。コンポーネント列名は、指定されている場合(次のショートカットの注意を参照)、任意の順序で指定できます。

      ショートカットを使用する場合は、オブジェクトIDに属性列名を設定しないでください。

      ショートカット。 - システムOIDベースのREF列をロードする場合は、列名に名前を設定しないでください。名前はAPIによって判断されます。ただし、外部データ型などの他の列属性は、プログラマが設定する必要があります。

      主キーREF列をロードしており、その主キーが複数の列で構成されている場合、ショートカットはそれぞれの列名に設定されません。ただし、外部データ型などの他の列属性は、プログラマが設定する必要があります。


      注意:

      コンポーネント列名がNULLの場合は、APIコードによって、主キーに定義された位置または順序で列名が決定されます。したがって、名前以外の列属性を設定する場合は、その属性がコンポーネントの列に適切な順序で設定されていることを確認してください。

    3. OCI_ATTR_DATA_TYPEを使用して外部列の型(ダイレクト・パスAPIに渡されるデータの型)を設定します。

    4. その他の外部列の属性(最大データ・サイズ、精度、スケールなど)を設定します。

    5. 列記述子へのハンドルを解放します。

    6. 手順4で作成された関数コンテキストOCIDirPathFuncCtxを、OCI_ATTR_DIRPATH_FN_CTXを使用して親の列オブジェクトのパラメータ・ハンドルに設定します。

列配列のREF列への割当て

例13-20は、REF列に子の列配列を割り当てる方法を示しています。

例13-20 REF列への子の列配列の割当て

OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
OCIDirPathColArray *dpfnca; /* direct path function column array */
sword error;

error = OCIHandleAlloc((void  *)dpfnctx, (void  **)&dpfnca,
                       OCI_HTYPE_DIRPATH_FN_COL_ARRAY,
                       (size_t)0, (void  **)0);

REFデータの列配列へのロード

列がスカラー列の場合は、その値のアドレスをOCIDirPathColArrayEntrySet()に渡して、その値を列配列に設定します。列がREFの場合は、かわりに、子の列配列ハンドルのアドレスを渡します。子の列配列には、REFの引数のデータが格納されます。

データをREF列にロードする手順は、次のとおりです。


注意:

スカラー・データのロードと異なるステップは、イタリック表記になっています。

REF列ごとに、次の操作を行います。

  1. 列がNULL以外の場合:

    1. REF引数の列ごとに、次の操作を行います。

      OCIDirPathColArrayEntrySet()を使用して、子列配列にデータを設定します。

    2. 子列配列ハンドルのアドレスをOCIDirPathColArrayEntrySet()に渡すことにより、REF列のデータを列配列に設定します。

  2. 列がNULLの場合:

    データのNULLアドレス、長さ0 (ゼロ)およびOCI_DIRPATH_COL_NULLフラグをOCIDirPathColArrayEntrySet()に渡して、REF列のデータを列配列に設定します。

NOT FINALオブジェクトおよびREF列のダイレクト・パス・ロード

SQLオブジェクトの継承は型の階層を形成するオブジェクト型のファミリ・ツリーに基づいていることに注意してください。型の階層は、スーパータイプという親オブジェクト型と、親から導出された、サブタイプという1つ以上のレベルの子オブジェクト型で構成されます。

継承階層

図13-2は、Person型の列の継承階層を示しています。Personスーパータイプは、NameAddressの2つの属性を持ち、階層の最上位にあります。Personには、EmployeeStudentの2つのサブタイプがあります。Employeeサブタイプには、ManagerDeptidの2つの属性があります。Studentサブタイプには、UnitsGPAの2つの属性があります。ParttimeEmployeeは、Employeeのサブタイプで、これの下に表示されます。サブタイプParttimeEmployeeには、1つの属性Hoursがあります。これらは、Person列に格納できる型です。

図13-2 Person型の列の継承階層

図13-2の説明は次にあります
「図13-2 Person型の列の継承階層」の説明

継承可能にするオブジェクト型に対して、オブジェクト型定義では、それが継承可能であることを指定する必要があることに注意してください。指定すると、そこからサブタイプを導出できます。継承可能にするオブジェクトを指定するには、型定義にキーワードNOT FINALを指定する必要があります。継承可能にしないオブジェクトを指定するには、型定義にキーワードFINALを指定する必要があります。FINAL型およびNOT FINAL型の定義の詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください。

Person型の列を含む表をダイレクト・パス・ロードする場合、実際の型セットには、NOT FINALPersonとその3つのサブタイプであるStudentEmployeeおよびParttimeEmployeeを含めることができます。このロードの継続時間中、ダイレクト・パス・ロードAPIがサポートするのは、このNOT FINAL列の固定的な派生型のロードのみであるため、ダイレクト・パス・ロードAPIでは、ロード対象となる型、その型に対してロードする属性およびその型の作成に使用する関数などを認識する必要があります。

そのため、派生型を記述およびロードするときは、ロード対象となるその型の全属性を指定する必要があります。サブタイプは、この型とその親の全属性に固有なすべてのオブジェクト属性のフラット表現とみなしてください。したがって、ロード対象の属性列すべてを記述してカウントする必要があります。

たとえば、ParttimeEmployeeのすべての列をロードするには、ロード対象となるNameAddressManagerDeptidおよびHoursの5つのオブジェクト属性を記述してカウントする必要があります。

ロード対象の固定的な派生型の記述

NOT FINALまたは置換可能オブジェクト列と固定的な派生型のREF列を記述する手順は、同じ型のFINAL列を記述する手順と類似していることに注意してください。

X型(XはオブジェクトまたはREF)のNOT FINAL列を記述するには、「列オブジェクトのダイレクト・パス・ロード」または「REF列のダイレクト・パス・ロード」を参照してください。次の各項で、この型のFINAL列について説明します。派生型(スーパータイプまたはサブタイプの場合があります)は、ロードの継続時間中固定されているため、NOT FINAL列を記述するためのクライアント側インタフェースは、FINAL列を記述する場合と同じです。

サブタイプは、この型とその親の全属性に固有なすべてのオブジェクト属性のフラット表現とみなすことができます。したがって、ロード対象の属性列すべてを記述してカウントする必要があります。

列配列の割当て

列配列の割当ては、同じ型のFINAL列の場合と同じです。

データの列配列へのロード

列配列へのデータのロードは、同じ型のFINAL列の場合と同じです。

オブジェクト表のダイレクト・パス・ロード

オブジェクト表とは、すべての行がオブジェクト(つまり、行オブジェクト)である表です。表の各列は、オブジェクト属性です。

オブジェクト表の記述

オブジェクト表の記述は、非オブジェクト表の記述と非常に類似しています。各オブジェクト属性が表の列です。唯一の相違点は、OIDがシステム生成、ユーザー生成または主キー・ベースの場合に、そのOIDの記述が必要になることです。

オブジェクト表を記述する手順は、次のとおりです。


注意:

非オブジェクト表のロードと異なるステップは、イタリック表記になっています。

オブジェクト属性列ごとに、次の操作を行います。

それぞれの型(NUMBERREFなど)に基づいて、各オブジェクト属性の列を必要に応じて記述します。

オブジェクト表がOID (Oracle Internet Directory)の場合は、次の操作を行います。

  1. オブジェクトIDがシステム生成の場合。

    何もする必要はありません。システムがすべての行オブジェクトのOIDを生成します。

  2. オブジェクトIDがユーザー生成の場合。

    1. 仮の名前(cust_oidなど)を使用してOIDの列名を表現します。

    2. OCI_ATTR_DIRPATH_OIDでOIDの列属性を設定します。

  3. オブジェクトIDが主キー・ベースの場合。

    1. OIDを構成しているすべての主キー列をロードします。

    2. OCI_ATTR_DIRPATH_OIDを設定しないでください。ダミーの名前を持つOID列は作成されていません。

列配列のオブジェクト表への割当て

例13-21は、列配列のオブジェクト表への割当ては、非オブジェクト表に列配列を割り当てる方法と同じであることを示しています。

例13-21 列配列のオブジェクト表への割当て

OCIDirPathColArray *dpca;  /* direct path column array */
sword error;

error = OCIHandleAlloc((void  *)dpctx, (void  **)&dpca,
                       OCI_HTYPE_DIRPATH_COLUMN_ARRAY,
                       (size_t)0, (void  **)0);

データの列配列へのロード

列配列へのデータのロードは、非オブジェクト表にデータをロードする方法と同じです。

NOT FINALオブジェクト表のダイレクト・パス・ロード

NOT FINALオブジェクト表は継承をサポートしますが、FINALオブジェクト表は継承をサポートできません。

NOT FINALオブジェクト表の記述

固定的な派生型のNOT FINALオブジェクト表の記述は、FINALオブジェクト表の記述と非常に類似しています。

固定的な派生型のNOT FINALオブジェクト表を記述する手順は、次のとおりです。


注意:

FINALオブジェクト表の記述と異なるステップは、イタリック表記になっています。

  1. OCI_ATTR_DIRPATH_OBJ_CONSTRを使用して、ダイレクト・パス・コンテキストにオブジェクト表のオブジェクト型を設定します。これは、スーパータイプまたは派生型に関係なく、ロードの継続時間中、この表へのロードにはオブジェクト型がデフォルトのオブジェクト・コンストラクタとして使用されることを意味します。

    text *obj_type;            /* the object type to load into this NOT FINAL */
                               /* object table */
    sword error;
    
    error = OCIAttrSet((void  *)dpctx,
                       OCI_HTYPE_DIRPATH_CTX,
                       (void  *) obj_type,
                       (ub4)strlen((const char *) obj_type),
                       OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);
    
  2. ロードする各オブジェクト属性列のデータ型に従って記述します。必要に応じて、オブジェクトIDを記述します。これは、FINALオブジェクト表を記述する方法と同じです。

列配列のNOT FINALオブジェクト表への割当て

NOT FINALオブジェクト表の列配列の割当ては、FINALオブジェクト表の場合と同じです。

ピース単位のダイレクト・パス・ロード

一度にメモリー内に格納できないデータのロードをサポートするために、ピース単位のロードを使用します。

ダイレクト・パスAPIでは、LONGとLOBの段階的なロードがサポートされています。これには、次の手順を順に実行します。

  1. 最初のピースをOCIDirPathColArrayEntrySet()を使用して列配列に設定し、OCI_DIRPATH_COL_PARTIALフラグに渡して、この列の全データのロードが完了していないことを示します。

  2. 列配列をストリームに変換します。

  3. ストリームをロードします。

  4. そのデータの次のピースを列配列に設定します。このピースが未完了の場合は、パーシャル・フラグを設定して手順2に戻ります。完了している場合は、OCI_DIRPATH_COL_COMPLETEフラグを設定して次の列へ続行します。

このアプローチは、本質的には列オブジェクトの大規模な属性やSQL文字列型の大規模な引数を扱う方法と同じです。


関連項目:

OCI_DIRPATH_COL_ERRORの値をOCIDirPathColArrayEntry()に渡して、エラー発生時に現在の列配列行を無視する必要があることを示す方法の詳細は、「OCI_DIRPATH_COL_ERROR」を参照してください。


注意:

コレクションは、このようにピース単位でロードしません。NESTED TABLEは、トップレベル表と同じように、個別にロードします。NESTED TABLEは段階的にロードでき、またピース単位でロードされた列を含めることができます。したがって、コレクションを格納している列には、OCI_DIRPATH_COL_PARTIALフラグを設定しないでください。

オブジェクト型のピース単位のロード

オブジェクトは、そのオブジェクトが格納されている親の表から個別の列配列にロードします。したがって、オブジェクトをピース単位でロードする必要がある場合は、子の列配列に要素を設定して、ピース化された要素を含める必要があります。

通常の手順は、次のとおりです。

  1. ピース化された要素に、OCI_DIRPATH_COL_PARTIALフラグを設定します。

  2. 子の列配列ハンドルを親の列配列に設定し、そのエントリもOCI_DIRPATH_COL_PARTIALフラグでマークします。

  3. 親の列配列をストリームに変換します。この結果、子の列配列もストリームに変換されます。

  4. ストリームをロードします。

  5. 手順1に戻り、その要素に対する残りのデータのロードを、完了するまで続行します。

ピース単位のロードには、いくつかのルールがあります。

  • パーシャル要素は、任意のレベルで一度に1つしか存在できません。1つのパーシャル要素が完了とマークされた後は、そのレベルの別の要素をパーシャル要素に設定できます。

  • 要素がパーシャルで、かつトップレベルでない場合は、制御階層上のその要素のすべての親にもパーシャルのマークを付ける必要があります。

  • ネスト・レベルが複数の場合は、対象データをストリームに変換できるレベルまで移動する必要があります。これがトップレベル表になります。


関連項目:

OCI_DIRPATH_COL_ERRORの値をOCIDirPathColArrayEntry()に渡して、エラー発生時に現在の列配列行を無視する必要があることを示す方法の詳細は、「OCI_DIRPATH_COL_ERROR」を参照してください。

ダイレクト・パス・コンテキスト・ハンドルとオブジェクト型の属性

次の説明では、付録Aにリストされているハンドルと属性の詳細を補足します。

ダイレクト・パス・コンテキストの属性

1つのダイレクト・パス・コンテキストの属性があります。

OCI_ATTR_DIRPATH_OBJ_CONSTR

オブジェクト型がNOT FINALオブジェクト表にロードされることを示します。

ttext *obj_type;            /* the object type to load into this NOT FINAL */
                           /* object table */
sword error;

error = OCIAttrSet((void  *)dpctx,
                   OCI_HTYPE_DIRPATH_CTX,
                   (void  *) obj_type,
                   (ub4)strlen((const char *) obj_type),
                   OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);

ダイレクト・パス関数コンテキストと属性

関数コンテキスト・ハンドルの属性の概要を、次に示します。

OCI_ATTR_DIRPATH_OBJ_CONSTR

オブジェクト型が置換可能なオブジェクト表にロードされることを示します。

text *obj_type; /* stores an object type name */
sword error;

error = OCIAttrSet((void  *)dpctx,
                   OCI_HTYPE_DIRPATH_CTX,
                   (void  *) obj_type,
                   (ub4)strlen((const char *) obj_type),
                   OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);

OCI_ATTR_NAME

関数コンテキストの作成時に、非スカラー列を記述する式に相当するOCI_ATTR_NAMEを設定します。次に、式の型を示すOCI属性を設定します。式の型は、それが列オブジェクト、REF列またはSQL文字列の列であるかに応じて異なります。

列オブジェクト

必要な式は、オブジェクト型名です。オブジェクト型はデフォルトのオブジェクト・コンストラクタとして使用されます。

式の型OCI_ATTR_DIRPATH_EXPR_TYPEOCI_DIRPATH_EXPR_OBJ_CONSTRに設定し、この式がオブジェクト型名であることを示します。

REF列

このオプションの式は、参照表名です。この表は、REF列が行オブジェクトを参照する参照元のオブジェクト表です。

式の型OCI_ATTR_DIRPATH_EXPR_TYPEOCI_DIRPATH_EXPR_REF_TBLNAMEに設定し、この式が参照オブジェクト表であることを示します。

このパラメータの動作は、設定の有無に関係なく、REFの型によって異なります。

  • 有効範囲なしのREF列(有効範囲なし、システムOIDベース)

    • このパラメータが設定されていない場合、このREF列には、有効範囲なしのREF列の定義により、参照表の名前が引数としてデータ行ごとに含まれている必要があります。

    • パラメータが設定されている場合、このREF列がロードの継続時間中に参照できるのは、指定されたオブジェクト表の行オブジェクトのみです。このREF列に、参照表の名前を引数として含めることはできません。(ダイレクト・パスAPIは、このパラメータをショートカットとしてユーザーに提供しています。ユーザーは、このパラメータをロードの継続時間中に同じ参照オブジェクト表を参照する有効範囲なしのREF列にロードします)。

  • 有効範囲付REF列(有効範囲付、システムOIDベースおよび主キー・ベース)

    • このパラメータが設定されていない場合、ダイレクト・パスAPIは、スキーマで指定されている参照表を使用します。

    • このパラメータが設定されている場合、参照表の名前は、この有効範囲付REF列のスキーマに指定されているオブジェクト表と一致している必要があります。表名が一致していない場合は、エラーが発生します。

    • このパラメータが設定されているかどうかに関係なく、この参照表の名前がデータ行に存在しているかどうかはAPIにとって問題ではありません。名前がデータ行にある場合、その名前はスキーマに指定されている表名と一致している必要があります。名前がデータ行にない場合、APIはスキーマに定義されている参照表を使用します。

SQL文字列の列

この必須式には、列に格納される値を導出するSQL文字列が含まれています。

式の型OCI_ATTR_DIRPATH_EXPR_TYPEOCI_DIRPATH_EXPR_SQLに設定し、この式がSQL文字列であることを示します。

OCI_ATTR_DIRPATH_EXPR_TYPE

この属性を使用して、非スカラー列の関数コンテキストに対して、OCI_ATTR_NAMEで指定した式の型を示します。

OCI_ATTR_NAMEが設定されている場合、OCI_ATTR_DIRPATH_EXPR_TYPEは必須です。

OCI_ATTR_DIRPATH_EXPR_TYPEに使用可能な値は、次のとおりです。

  • OCI_DIRPATH_EXPR_OBJ_CONSTR

    • 式がオブジェクト型名であること、この式が列オブジェクトに対するデフォルトのオブジェクト・コンストラクタとして使用されることを示します。

    • 列オブジェクトには必須です。

  • OCI_DIRPATH_EXPR_REF_TBLNAME

    • 式が参照オブジェクト表の名前であることを示します。この表は、REF列が行オブジェクトを参照する参照元のオブジェクト表です。

    • REF列の場合は、オプションです。

  • OCI_DIRPATH_EXPR_SQL

    • 式は列に格納されている値を導出するために実行されるSQL文字列であることを示します。

    • SQL文字列の列の場合は、必須です。

例13-22は、前述のルールおよび値を例示した疑似コードを示しています。

例13-22 OCI_ATTR_DIRPATH_EXPR_TYPE属性への値の指定

OCIDirPathFuncCtx  *dpfnctx; /* function context for this nonscalar column */
ub1 expr_type; /* expression type */
sword error;

if (...) /* (column type is an object) */
expr_type = OCI_DIRPATH_EXPR_OBJ_CONSTR;
...
if (...) /* (column type is a REF && function context name exists) */
expr_type = OCI_DIRPATH_EXPR_REF_TBLNAME;
...
if (...) /* (column type is a SQL string) */
expr_type = OCI_DIRPATH_EXPR_SQL;
...
error = OCIAttrSet((void  *)(dpfnctx),
                   OCI_HTYPE_DIRPATH_FN_CTX,
                   (void  *)&expr_type, (ub4)0,
                   OCI_ATTR_DIRPATH_EXPR_TYPE, ctlp->errhp_ctl);

OCI_ATTR_DIRPATH_NO_INDEX_ERRORS

OCI_ATTR_DIRPATH_NO_INDEX_ERRORSが1である場合、索引はロード中のどの時点でも使用不可に設定されません。索引エラーが検出された場合、ロードは終了します。つまり、行はロードされず、索引はそのままとなります。デフォルトは0 (ゼロ)です。

OCI_ATTR_NUM_COLS

この属性は、非スカラー列用にロードまたは処理する属性や引数の数を記述します。このパラメータは、列リストが取り出される前に設定する必要があります。式の型は、それが列オブジェクト、SQL文字列の列またはREF列であるかに応じて異なります。

列オブジェクト

この列オブジェクト用にロードするオブジェクト属性列の数。

SQL文字列の列

SQL文字列に渡す引数の数。

引数が関数内で繰り返して使用される場合も、1つとしてカウントしてください。

REF列

REF列が指し示す必要のある行オブジェクトを識別するREF引数の数。

必要な引数の数は、REF列の型によって異なります。

  • 有効範囲なしのREF列(有効範囲なし、システムOIDベースのREF列)

    • OCI_DIRPATH_EXPR_REF_TBLNAMEを使用している場合。参照表の名前の引数はなく、OID値の引数が1つです。(OID値のみがデータ行にある。)

    • OCI_DIRPATH_EXPR_REF_TBLNAMEを使用していない場合。参照表の名前の引数が1つとOID値の引数が1つです。(参照表名とOID値の両方がデータ行にある。)

  • 有効範囲付REF列(有効範囲付、システムOIDベースおよび主キー・ベース)

    • OCI_DIRPATH_EXPR_REF_TBLNAMEを使用しているかどうかにかかわらず、オブジェクトIDを構成している列数がNの場合、受入れ可能な数はNまたはN+1です。参照表の名前がデータ行にない場合、最小値はNです。参照表の名前がデータ行にある場合は、N+1を使用します。

    • REFがシステムOIDベースの場合、Nは1になります。REFが主キー・ベースの場合、Nは主キーを構成するコンポーネント列の数になります。参照表の名前がデータ行にある場合は、Nに1を加算します。


    注意:

    NまたはN+1以外のある数のREF引数で渡された場合のエラー・メッセージを簡単化するには、Nを予期している際に何らかの数の引数が検出されたことだけを示すエラー・メッセージにします。メッセージではN+1について記述されていませんが、N+1は受入れ可能である(参照表名が必要ない場合でも)ため、エラー・メッセージは表示されません。

OCI_ATTR_NUM_ROWS

OCI_HTYPE_DIRPATH_FN_CTX (関数コンテキスト)に対して使用される場合、この属性は、取出し専用のため、ユーザーによる設定はできません。この属性は、OCIAttrGet()にのみ使用でき、OCIAttrSet()には使用できません。OCIAttrGet()をOCI_ATTR_NUM_ROWS使用してコールすると、それまでにロードされた行数が戻されます。

ただし、属性OCI_ATTR_NUM_ROWSは、OCI_HTYPE_DIRPATH_CTX (表レベルのコンテキスト)に対して使用する場合は、設定およびユーザーによる取出しの両方が可能です。

OCIAttrSet()OCI_ATTR_NUM_ROWSOCI_HTYPE_DIRPATH_CTXを使用してコールすると、表レベルの列配列に割り当てる行数が設定されます。設定されない場合、ダイレクト・パスAPIコードは、レコード最大サイズと転送バッファのサイズに基づいて適切な数を導出します。割り当てた行数を確認するには、表レベルの列配列については、OCI_ATTR_NUM_ROWSOCI_HTYPE_DIRPATH_COLUMN_ARRAYで使用し、関数列配列については、OCI_HTYPE_DIRPATH_FN_COL_ARRAYを使用して、OCIAttrGet()をコールします。

OCIAttrGet()OCI_ATTR_NUM_ROWSOCI_HTYPE_DIRPATH_CTXでコールすると、それまでにロードされた行数が戻されます。

この属性は、関数コンテキストではユーザーは設定できません。OCI_ATTR_NUM_ROWSOCIAttrSet()により、関数列配列内で必要な行数を指定することはできません。これは、すべての関数列配列が、表レベルの列配列と同じ行数を持っているためです。この属性は、表レベルのコンテキストでのみ設定することができ、関数コンテキストでは設定できません。

ダイレクト・パス列パラメータ属性

オブジェクト、SQL文字列またはREF列を記述すると、その列属性の1つが関数コンテキストになります。

列がオブジェクトの場合、その関数コンテキストには、そのオブジェクト型とオブジェクト属性が記述されます。列がSQL文字列の場合、関数コンテキストは、コール対象の式を記述します。列がREFの場合、関数コンテキストは、参照表の名前と行オブジェクトの識別子を記述します。

例13-23は、関数コンテキストを列属性として設定し、OCI_ATTR_DIRPATH_FN_CTXOCIAttrSet()コールで使用することを示しています。

例13-23 列属性としての関数コンテキストの設定

OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
sword error;

error = OCIAttrSet((void  *)colDesc,
                   OCI_DTYPE_PARAM,
                   (void  *)(dpfnctx), (ub4)0,
                   OCI_ATTR_DIRPATH_FN_CTX, ctlp->errhp_ctl);

列パラメータ・コンテキスト・ハンドルの属性について次に説明します。

OCI_ATTR_NAME

次に、ネストした表、オブジェクト表、SQL文字列の列およびREF列をロードするためのネーミング規則について説明します。

通常、オブジェクト表のシステム生成オブジェクトID (OID)列やネストした表のSETID (SID)列など、プログラマにとって不明なシステム名を持つシステム列にデータをロードする場合、あるいは列がデータベース表の列を持たない引数(SQL文字列やREF引数など)である場合は、ダミーの名前を使用します。

列はデータベース表の列であっても、ダミーの名前を使用した場合は、その列がデータベースで識別されない名前の場合でも関数が識別できるように、列属性を設定する必要があります。

ネーミング規則は、次のとおりです。

  • 子のネストした表のSETID (SID)列

    SETID列は必須です。ダミーの名前を使用して、そのOCI_ATTR_NAMEを設定します。これは、APIでは、ユーザーがそのシステム名を認識しているとはみなしていないためです。これがSID列であることを示すように、OCI_ATTR_DIRPATH_SIDで列属性を設定します。

  • オブジェクト表のオブジェクトID (OID)列

    次の場合、オブジェクトIDは必須です。

    1. オブジェクトIDがシステム生成の場合。

      列名にダミーの名前(たとえば、cust_oid)を使用します。

      OCI_ATTR_DIRPATH_OIDで列属性を設定します。その結果、ダミーの名前を持つ列が複数ある場合にも、システム生成のOIDを表す列を識別できます。

    2. オブジェクトIDが主キー・ベースの場合。

      列名にはダミーの名前を使用できません。したがって、OCI_ATTR_DIRPATH_OIDを使用してその列属性を設定する必要はありません。

  • SQL文字列の引数

    1. OCI_ATTR_NAMEで属性の列名を設定します。

    2. SQL文字列の引数の順序は、重要ではありません。SQL文字列で使用されている順序と一致させる必要はありません。

    3. SQL文字列の引数には、ネーミング規則が適用されます。

      • 引数名は、SQL文字列で使用されているバインド変数名と内容が一致している必要がありますが、大/小文字区別を一致させる必要はありません。たとえば、SQL文字列がsubstr(:INPUT_STRING, 3, 5)の場合は、引数名をinput_stringにできます。

      • 1つの引数がSQL文字列で繰り返し使用される場合、それを一度宣言した後は、1つの引数としてカウントできます。

  • REF引数

    1. OCI_ATTR_NAMEで属性の列名を設定します。

      REF引数の順序は重要です。

      • 参照表の名前が指定されている場合は、その名前を最初のREF引数に指定します。

      • オブジェクトIDは、システム生成または主キー・ベースに関係なく、次のREF引数に指定します。

    2. REFの引数には、ネーミング規則が適用されます。

      • 参照表名の引数に対しては、列名にref-tblなどのダミーの名前を使用します。

      • システム生成OIDの引数に対しては、列名にsys-OIDなどのダミーの名前を使用します。注意: この列は、引数として使用され、ロード対象の列としては使用されないため、OCI_ATTR_DIRPATH_OIDで設定しないでください。

      • 主キー・ベースのオブジェクトIDに対しては、ロード対象のすべての主キー列をリストします。OIDに対してダミーの名前を作成する必要はありません。コンポーネント列名は、指定されている場合(次のショートカットのステップを参照)、任意の順序で指定できます。

    3. ショートカットを使用する場合は、オブジェクトIDに属性列名を設定しないでください。

      • ショートカット。- システムOIDベースのREF列をロードする場合は、列名に名前を設定しないでください。名前はAPIによって判断されます。ただし、外部データ型などの他の列属性は、プログラマが設定する必要があります。

      • 主キーREF列をロードしており、その主キーが複数の列で構成されている場合、ショートカットはそれぞれの列名に設定されません。ただし、外部データ型などの他の列属性は、プログラマが設定する必要があります。


        注意:

        コンポーネント列名がNULLの場合は、APIコードによって、主キーに定義された位置または順序で列名が決定されます。したがって、名前以外の列属性を設定する場合は、その属性がコンポーネントの列に適切な順序で設定されていることを確認してください。

OCI_ATTR_DIRPATH_SID

列がネストした表のSETID列であることを示します。ネストした表にロードする場合は必須です。

ub1 flg = 1;
sword error;

error = OCIAttrSet((void  *)colDesc, 
                   OCI_DTYPE_PARAM,
                   (void  *)&flg, (ub4)0,
                   OCI_ATTR_DIRPATH_SID, ctlp->errhp_ctl);

OCI_ATTR_DIRPATH_OID

列がオブジェクト表のオブジェクトID列であることを示します。

ub1 flg = 1;
sword error;

error = OCIAttrSet((void  *)colDesc, 
                   OCI_DTYPE_PARAM,
                   (void  *)&flg, (ub4)0,
                   OCI_ATTR_DIRPATH_OID, ctlp->errhp_ctl);

非スカラー列のダイレクト・パス関数列配列ハンドル

列がオブジェクト、SQL文字列またはREFの場合は、OCI_HTYPE_DIRPATH_FN_COL_ARRAYハンドル型を使用します。構造体OCIDirPathColArrayは、スカラー列と非スカラー列の両方の場合で同じです。

例13-24は、関数コンテキストに子の列配列を割り当てる方法を示しています。

例13-24 関数コンテキストへの子の列配列の割当て

OCIDirPathFuncCtx *dpfnctx; /* direct path function context */
OCIDirPathColArray *dpfnca; /* direct path function column array */
sword error;

error = OCIHandleAlloc((void  *)dpfnctx, (void  **)&dpfnca,
                       OCI_HTYPE_DIRPATH_FN_COL_ARRAY,
                       (size_t)0, (void  **)0);

OCI_ATTR_NUM_ROWS属性

OCI_HTYPE_DIRPATH_FN_COL_ARRAY (関数列配列)に対して使用される場合、この属性は、取出し専用のため、ユーザーによる設定はできません。OCI_ATTR_NUM_ROWS属性を関数OCIAttrGet()でコールすると、関数列配列に割り当てられた行数が戻されます。