17.00 - 17.05 - 設計上の考慮事項 - Advanced SQL Engine - Teradata Database

Teradata Vantage™ - SQL外部ルーチン プログラミング

Product
Advanced SQL Engine
Teradata Database
Release Number
17.00
17.05
Published
2020年6月
Content Type
プログラミング リファレンス
Publication ID
B035-1147-170K-JPN
Language
日本語 (日本)

参加する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の反復実行間でステータス情報を維持するために、コンテキスト オブジェクトが必要なときには、適切なフェーズでコンテキスト オブジェクトを定義、割り当て、設定および取得するコードを必要に応じて組み込む必要があります。