For better performance, you can use a byte array to hold the data to retain between iterations in Java table UDFs.
The methods for allocating the context object, setting it and retrieving it are:
- Tbl.allocCtx(int) without a return value.
- Tbl.setCtxObject(byte[]) without a return value.
- getCtxObject(byte[]) with a return value of byte[].
Note that you will have to provide methods for serializing and deserializing the context object accordingly.
The following is an example that uses a byte array to hold an integer value as the context object. The supporting methods byteArrayToInt(byte []) and intToByteArray(int) are provided as needed.
import com.teradata.fnc.Tbl;
import java.sql.*;
public class Measure
{
public static final int byteArrayToInt(byte [] b)
{
return (b[0] << 24)
+ ((b[1] & 0xFF) << 16)
+ ((b[2] & 0xFF) << 8)
+ (b[3] & 0xFF);
}
public static final byte[] intToByteArray(int value)
{
return new byte[] {
(byte)(value >>> 24),
(byte)(value >>> 16),
(byte)(value >>> 8),
(byte)value };
}
public static void j_noop_table1_bytearray(double a, double[] c) throws SQLException
{
byte[] ctxByteArr = {0, 0, 0, 0}; // scratch pad
int count;
try
{
int [] phase = new int[1];
Tbl tbl = new Tbl();
int mode = tbl.getPhase(phase);
if (mode!=Tbl.TBL_MODE_VARY) throw new SQLException("Wrong Mode", "U0001");
switch(phase[0])
{
case Tbl.TBL_PRE_INIT:
tbl.allocCtx(4); // 4-byte integer
break;
case Tbl.TBL_INIT:
count = 1;
ctxByteArr = intToByteArray(count);
tbl.setCtxObject(ctxByteArr);
break;
case Tbl.TBL_BUILD:
ctxByteArr = (byte[])tbl.getCtxObject(ctxByteArr);
count = byteArrayToInt(ctxByteArr);
if (count == 0) throw new SQLException("no more data", "02000");
c[0] = a;
count--;
ctxByteArr = intToByteArray(count);
tbl.setCtxObject(ctxByteArr);
break;
case Tbl.TBL_FINI:
case Tbl.TBL_END:
case Tbl.TBL_ABORT:
default:
break;
}
} catch (ClassNotFoundException e) {
throw new SQLException("ClassNotFoundException", "U0002");
} catch(IOException e){
throw new SQLException("IOException", "U0003");
}
}
}