参加する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();
}
}
}