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にデータが存在するとは限りません。

Tbl.getPhase()を使用するメソッドの実装では、次のコード抜粋をガイドラインとして使用します。

public class local_ctx {
   String xml_ctx;
   public void local_ctx() {
      xml_ctx = new String(50);
   }
} ;

public class UDFExample {

   public static void getStoreData( int storeData,
                                    int[] storeNo,
                                    int[] itemNo)
   {
      Tbl tbl = new Tbl();
      int[] phase = new int[1];
      local_ctx state_info;
      if ( tbl.getPhase(phase) != Tbl.TBL_MODE_VARY )
      {
         /* set SQLSTATE to an error and return */
         throw new SQLException("Wrong mode", "38U06");
         return;
      }

      /* depending on the phase decide what to do */
      switch(phase[0])
      {
         case Tbl.TBL_PRE_INIT:
            state_info = new local_ctx();
            ...
            break;
         case Tbl.TBL_INIT:
            /* Allocate scratchpad to retain data between iterations. */
            tbl.allocCtx(state_info);
            /* Preprocess data here. */
            ...
            break;
         case Tbl.TBL_BUILD:
            /* Get scratchpad and build the result row here. */
            state_info = (local_ctx)tbl.getCtxObject();
            ...
            /* Or, if no more rows to build, set SQLSTATE to "02000". */
            throw new SQLException("no more data", "02000");
            ...
            break;
         case Tbl.TBL_FINI:
            /* Reset for the next set of data. */
            ...
            break;
         case Tbl.TBL_END:
            /* Everyone done. */
            ...
            break;
      }
   }
}

使用するテーブルUDFが関数を実行しているAMP上のすべての入力ローを受け取るまで結果ローを作成しない場合は、Tbl.getPhase()の代わりにTBL_LASTROWオプションを指定したTbl.getPhaseEx()を使用します。これは、TBL_BUILD_EOFフェーズで行を作成します。Tbl.getPhaseEx()を使用するUDFの実装では、次のコード抜粋をガイドラインとして使用します。

public class local_ctx {
   String xml_ctx;
   public void local_ctx() {
      xml_ctx = new String(50);
   }
} ;

public class UDFExample {

   public static void getStoreData( int storeData,
                                    int[] storeNo,
                                    int[] itemNo)
   {
      Tbl tbl = new Tbl();
      int[] phase = new int[1];
      local_ctx state_info;
      if ( tbl.getPhaseEx(phase, Tbl.TBL_LASTROW) != Tbl.TBL_MODE_VARY )
      {
         /* set SQLSTATE to an error and return */
         throw new SQLException("Wrong mode", "38U06");
         return;
      }

      /* depending on the phase decide what to do */
      switch(phase[0])
      {
         case Tbl.TBL_PRE_INIT:
            state_info = new local_ctx();
            ...
            break;
         case Tbl.TBL_INIT:
            /* Allocate scratchpad to retain data between iterations. */
            tbl.allocCtx(state_info);
            /* Preprocess data here. */
            ...
            break;
         case Tbl.TBL_BUILD:
            /* Get scratchpad and save data here. */
            state_info = (local_ctx)tbl.getCtxObject();
            ...
            /* Set SQLSTATE to "02000". */
            throw new SQLException("no more data", "02000");
            ...
            break;
         case Tbl.TBL_BUILD_EOF:
            /* Get scratchpad and build the result row here. */
            state_info = (local_ctx)tbl.getCtxObject();
            ...
            /* Or, if no more rows to build, set SQLSTATE to "02000". */
            throw new SQLException("no more data", "02000");
            ...
            break;
         case Tbl.TBL_FINI:
            /* Reset for the next set of data. */
            ...
            break;
         case Tbl.TBL_END:
            /* Everyone done. */
            ...
            break;
      }
   }
}

テーブルUDFの呼び出しごとに新しいローを取得する必要がある場合は、Tbl.TBL_NEWROWオプションを指定したTbl.getPhaseEx()を使用します。次に示すコードの抜粋は、これの使用例です。

import java.io.*;
import java.sql.*;
import com.teradata.fnc.*;

public class TableFunctions
{
   static boolean debug = true;

   public static void fnc_phase_new1(int in1, String in2, int[] out1, String[] out2)
      throws SQLException, Exception
   {
      class GenCtx implements Serializable
      {
         public int count;
         public GenCtx(){}
         public GenCtx (int count)
         {
             this.count = count;
         }
      }
      try
      {
         int [] phase = new int[1];
         GenCtx obj;
         Tbl tbl = new Tbl();

         // Only ask for the phase on each row
         int mode = tbl.getPhaseEx(phase, tbl.TBL_NOOPTIONS);

         if (mode != Tbl.TBL_MODE_VARY) {
            if (debug)
               System.err.println("Table function being called in unsupported context");
            throw new SQLException("Table function being called in unsupported context", "U0006");
         }
         if (debug) System.err.println("MODE =" + mode);
         if (debug) System.err.println("Phase =" + phase[0]);

         switch(phase[0])
         {
            case Tbl.TBL_PRE_INIT:

            // Ask for a new row on each call to build
            tbl.getPhaseEx(phase, tbl.TBL_NEWROW);

            if (debug) System.err.println("Phase: TBL_PRE_INIT");
            //Init and allocate the context
            obj = new GenCtx();
            tbl.allocCtx(obj);
            tbl.setCtxObject(obj);

            trace ("\n In Pre Init");

            break;
            case Tbl.TBL_INIT:
            if (debug) System.err.println("Phase: TBL_INIT");

            //Get the context
            obj = (GenCtx)tbl.getCtxObject();
            //set value and store
            obj.count = 1;
            tbl.setCtxObject(obj);

            trace ("\n In Init");

            break;
            case Tbl.TBL_BUILD:
            if (debug) System.err.println("Phase: TBL_BUILD");
            //Get the context
            obj = (GenCtx)tbl.getCtxObject();
            if (debug){
               System.err.println("Phase: TBL_BUILD getObject ="+obj+", count="+obj.count);
            }
               trace ("\n In Build, input 1 is " + in1);
            out1[0] = in1;
            out2[0] = in2;
            if (debug)
               System.err.println("Phase: TBL_BUILD in1"+in1+", in2="+in2+", out1[0]="+out1[0]+", out2[0]="+out2[0]);
            break;
            case Tbl.TBL_BUILD_EOF:
            trace ("\n In Build_EOF");
            if (debug) System.err.println("Phase: TBL_BUILD_EOF");
            break;
            case Tbl.TBL_FINI:
            trace ("\n In FINI");
            if (debug) System.err.println("Phase: TBL_FINISH");
            break;
            case Tbl.TBL_END:
            trace ("\n In END");
            if (debug) System.err.println("Phase: TBL_END");
            break;
            case Tbl.TBL_ABORT:
            trace ("\n In ABORT");
            if (debug) System.err.println("Phase: TBL_ABORT");
            break;
            default:
            throw new SQLException("Entering default phase.", "U0006");
         }
      } catch (ClassNotFoundException e)
      {
         e.printStackTrace();
      } catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}