参加するAMP vprocは、SELECT文でテーブル関数の前に指定されている相関テーブル名から関数に提供される入力データに関連する行を含んでいます。この場合の前提は、入力引数によって処理対象が決定されるということです。関数の各コピーは、それ以上のデータがないという条件を示して関数が戻るまで、同じ入力データで繰り返し呼び出されます。
このモードでデータベースの外部から追加のデータを読み取ることも場合によっては可能ですが、通常は機能しません。これは、選択対象のデータベース行がどこに存在するかに基づいて、参加するAMP vprocが決定されるためです。すべてのAMP vprocにデータが存在するとは限りません。
ガイドラインとして以下のコード抜粋を使用してFNC_GetPhaseを用いた関数を実装します。
typedef struct {
scratch_XML xml_ctx;
} local_ctx;
FNC_Phase Phase;
local_ctx *state_info;
if ( FNC_GetPhase(& Phase) != TBL_MODE_VARY)
{
/* Set sqlstate to an error and return. */
strcpy(sqlstate, "U0005");
return;
}
/* depending on the phase decide what to do */
switch(Phase)
{
case TBL_PRE_INIT:
{
/* Allocate scratchpad to retain data between iterations. */
state_info = FNC_TblAllocCtx(sizeof(local_ctx));
break;
}
case TBL_INIT:
{
/* Get scratchpad. */
state_info = FNC_TblGetCtx;
/* Preprocess data here. */
...
break;
}
case TBL_BUILD:
{
/* Get scratchpad and build the result row here. */
state_info = FNC_TblGetCtx;
...
/* Or, if no more rows to build, set sqlstate to "02000". */
strcpy(sqlstate, "02000");
...
break;
}
case TBL_FINI:
{
/* Reset for the next set of data. */
state_info = FNC_TblGetCtx;
...
break;
}
case TBL_END:
{
/* Everyone done. */
...
break;
}
}
使用するテーブル関数が関数を実行しているAMP上のすべての入力ローを受け取るまで結果ローを作成しない場合は、FNC_GetPhaseの代わりにFNC_GetPhaseExとTBL_LASTROWオプションを使用できます。これは、TBL_BUILD_EOFフェーズで行を作成します。ガイドラインとして以下のコード抜粋を使用してFNC_GetPhaseExを用いた関数を実装します。
typedef struct {
scratch_XML xml_ctx;
} local_ctx;
FNC_Phase Phase;
local_ctx *state_info;
if ( FNC_GetPhaseEx(& Phase, TBL_LASTROW) != TBL_MODE_VARY)
{
/* Set sqlstate to an error and return. */
strcpy(sqlstate, "U0005");
return;
}
/* depending on the phase decide what to do */
switch(Phase)
{
case TBL_PRE_INIT:
{
/* Allocate scratchpad to retain data between iterations. */
state_info = FNC_TblAllocCtx(sizeof(local_ctx));
break;
}
case TBL_INIT:
{
/* Get scratchpad. */
state_info = FNC_TblGetCtx;
/* Preprocess data here. */
...
break;
}
case TBL_BUILD:
{
/* Get scratchpad and add data here. */
state_info = FNC_TblGetCtx;
...
/* Set sqlstate to "02000" to indicate not to output rwsult rows here. */
strcpy(sqlstate, "02000");
...
break;
}
case TBL_BUILD_EOF:
{
/* Get scratchpad and build result row here. */
state_info = FNC_TblGetCtx;
...
/* Or, if no more rows to build, set sqlstate to "02000". */
strcpy(sqlstate, "02000");
...
break;
}
case TBL_FINI:
{
/* Reset for the next set of data. */
state_info = FNC_TblGetCtx;
...
break;
}
case TBL_END:
{
/* Everyone done. */
...
break;
}
}
テーブル関数の呼び出しごとに新しいローを取得する必要がある場合は、TBL_NEWROWオプションを指定したFNC_GetPhaseExを使用します。次に示すコードの抜粋は、これの使用例です。
{
FNC_Phase Phase;
/* Make sure the function is called in the supported context. */
/* Only ask for the phase on each row. */
switch (FNC_GetPhaseEx(&Phase, TBL_NOOPTIONS))
{
case TBL_MODE_CONST:
strcpy(sqlstate, "U0005");
strcpy((char *) errormsg, "Table function being called in unsupported mode.");
return;
case TBL_MODE_VARY:
switch(Phase)
{
case TBL_PRE_INIT:
/* Ask for a new row on each call to build */
FNC_GetPhaseEx(&Phase,TBL_NEWROW);
break;
case TBL_INIT:
break;
case TBL_BUILD:
*out1 = *in1;
strcpy((char*)out2,(char*)in2);
break;
case TBL_FINI:
break;
case TBL_END:
break;
}
break;
}
}
上記のサンプル コードは、単に入力引数の値を出力列として返しているだけです。そのため、UDFテーブルの反復実行間でステータス情報を維持する、コンテキスト オブジェクトは必要ありません。テーブルUDFの反復実行間でステータス情報を維持するために、コンテキスト オブジェクトが必要なときには、適切なフェーズでコンテキスト オブジェクトを定義、割り当て、設定および取得するコードを必要に応じて組み込む必要があります。