Design Considerations | Variable Mode Table Function | Teradata Vantage - Design Considerations - Analytics Database - Teradata Vantage

SQL External Routine Programming

Deployment
VantageCloud
VantageCore
Edition
Enterprise
IntelliFlex
VMware
Product
Analytics Database
Teradata Vantage
Release Number
17.20
Published
June 2022
Language
English (United States)
Last Update
2023-07-11
dita:mapPath
iiv1628111441820.ditamap
dita:ditavalPath
qkf1628213546010.ditaval
dita:id
B035-1147
lifecycle
latest
Product Category
Teradata Vantageā„¢

The AMP vprocs that participate are those containing rows pertaining to the input data provided to the function from the correlated table name specified prior to the table function in the SELECT statement. The assumption is that the input argument determines what to process. Each copy of the function will be called with the same input data repeatedly until the function returns with the no more data condition.

Although it might be possible to read additional data from outside the database in this mode, it probably will not work. This is because the participating AMP vprocs are determined based on where the selected database rows reside. It might not be on all AMP vprocs.

Use the following code excerpt as a guideline to implement your function using 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;
   }
}

If your table function does not build a result row until after it receives all of the input rows for the AMP on which it runs, you can use FNC_GetPhaseEx with the TBL_LASTROW option instead of FNC_GetPhase. This will build the row during the TBL_BUILD_EOF phase. Use the following code excerpt as a guideline to implement your function using 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;
   }
}
If you want to get a new row on each table function invocation, use FNC_GetPhaseEx with the TBL_NEWROW option. The following code excerpt shows an example of this usage.
This sample code is simply returning the values of the input arguments as output columns, so there is no need for a context object to retain status information between iterations of the table UDF. If you need to use a context object to retain status information between iterations of a table UDF, you must include code for defining, allocating, setting and getting the context object in the appropriate phases accordingly.
{
   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;
   }
}