The implementation file contains the definitions of the functions you use to create a custom function. Create an implementation file using C. You can use one implementation file for one or more custom functions. You can also use one implementation file to define both the validation and runtime functions of a custom function.
The following example shows the echo.c implementation file for the ECHO custom function:
/***************************************************************************
* ECHO function Procedure File
*
* This file contains code that creates the ECHO function, which the
* Integration Service calls during a workflow.
***************************************************************************/
/* Informatica ECHO function example developed using the Custom Function
* API.
* Filename: Echo.c
* An example of a custom function developed using PowerCenter
*
* The purpose of the ECHO function is to return the input value to the user.
*
*/
/***************************************************************************
Includes
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include "sdkexpr/exprsdk.h"
#define SAMPLE_EXPR_EXPORTS
#include "SampleExprPlugin.hpp"
static IUNICHAR ECHO_STR[80];
/***************************************************************************
Functions
***************************************************************************/
/***************************************************************************
Function: INFA_EXPR_GetPluginVersion
Description: Defines the version of the plug-in. It must be the same as the
Custom Function API version. Returns ISUCCESS if the plug-in version
matches the Custom Function API version. Otherwise, returns IFAILURE.
Input: sdkVersion - Current version of the Custom Function API.
Output: pluginVersion - Set the version of the plug-in.
Remarks: Custom Function API checks for compatibility between itself and the
plug-in version.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS INFA_EXPR_GetPluginVersion(INFA_VERSION* sdkVersion, INFA_VERSION* pluginVersion)
{
pluginVersion->m_major = 1;
pluginVersion->m_minor = 0;
pluginVersion->m_patch = 0;
INFA_EXPR_STATUS retStatus;
retStatus.status = ISUCCESS;
retStatus.errMsg = NULL;
return retStatus;
}
/***************************************************************************
Function: INFA_EXPR_DestroyString
Description: Destroys all strings the plug-in returns. For example, it
destroys error messages or the return value of other function calls, such
as getFunctionDescription. Returns no value.
Input: The pointer to the allocated string.
Output: N/A
Remarks: Frees the memory to avoid issues with multiple heaps.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC void INFA_EXPR_DestroyString(IUNICHAR *strToDelete)
{
delete [] strToDelete;
}
/***************************************************************************
Function: INFA_EXPR_ValidateGetUserInterface
Description: Returns function pointers to the validation functions. Returns
ISUCCESS when the plug-in implemented the function. Returns IFAILURE
when the plug-in did not implement the function or another error occurred.
Input: Namespace and name of function.
Output: Functions. The plug-in needs to set various function pointers.
Remarks: Check the namespace and function name for validaity. Set the various
function pointers appropriately.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS INFA_EXPR_ValidateGetUserInterface(IUNICHAR* ns, IUNICHAR* sFuncName,
INFA_EXPR_VALIDATE_METHODS* functions)
{
INFA_EXPR_STATUS retStatus;
retStatus.errMsg = NULL;
// check function name is not null
if (!sFuncName)
{
retStatus.status = IFAILURE;
return retStatus;
}
// set the appropriate function pointers
functions->validateFunction = validateFunctionEcho;
functions->getFunctionDescription = getDescriptionEcho;
functions->getFunctionPrototype = getPrototypeEcho;
functions->pushdownFunction = pushdownFunctionEcho;
retStatus.status = ISUCCESS;
return retStatus;
}
/***************************************************************************
Function: INFA_EXPR_ModuleGetUserInterface
Description: Sets the function pointers for module-level interaction.
Returns ISUCCESS when functions pointers are set appropriately. Otherwise,
returns IFAILURE.
Input: N/A
Output: Functions. The plug-in needs to set various function pointers.
Remarks: Set the module init/deinit function pointers.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS INFA_EXPR_ModuleGetUserInterface(INFA_EXPR_LIB_METHODS* functions)
{
functions->module_init = moduleInitEcho;
functions->module_deinit = moduleDeinitEcho;
INFA_EXPR_STATUS retStatus;
retStatus.status = ISUCCESS;
retStatus.errMsg = NULL;
return retStatus;
}
/***************************************************************************
Function: INFA_EXPR_FunctionGetUserInterface
Description: Sets the function pointers for function-level interaction.
PowerCenter calls this function for every custom function this library
implements. Returns ISUCCESS when The plugin implements this function and
sets the function pointers correctly. Otherwise, returns IFAILURE.
Input: Namespace and name of function.
Output: Functions. The plug-in needs to set function pointers for function
init/deinit.
Remarks: Set the function init/deinit function pointers.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS INFA_EXPR_FunctionGetUserInterface(IUNICHAR* nameSpaceName,
IUNICHAR* functionName,
INFA_EXPR_FUNCTION_METHODS* functions)
{
functions->function_init = functionInitEcho;
functions->function_deinit = functionDeinitEcho;
INFA_EXPR_STATUS retStatus;
retStatus.status = ISUCCESS;
retStatus.errMsg = NULL;
return retStatus;
}
/***************************************************************************
Function: INFA_EXPR_FunctionInstanceGetUserInterface
Description: Sets the function pointers for function instance-level
interaction. PowerCenter calls this function for every custom function this
library implements. Returns ISUCCESS when The plugin implements this
function and sets the function pointers correctly. Otherwise, returns
IFAILURE.
Input: Namespace and name of function.
Output: Functions. The plug-in needs to set function pointers for instance
init/deinit/processrow.
Remarks: Set the function instance init/deinit/processrow function pointers.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS INFA_EXPR_FunctionInstanceGetUserInterface(IUNICHAR* nameSpaceName,
IUNICHAR* functionName,
INFA_EXPR_FUNCTION_INSTANCE_METHODS* functions)
{
functions->fnInstance_init = functionInstInitEcho;
functions->fnInstance_processRow = processRowEcho;
functions->fnInstance_deinit = functionInstDeinitEcho;
INFA_EXPR_STATUS retStatus;
retStatus.status = ISUCCESS;
retStatus.errMsg = NULL;
return retStatus;
}
/***************************************************************************
Function: INFA_EXPR_getDescriptionEcho
Description: Gets the description of the ECHO function. It calls
destroyString to delete the arguments from memory when usage is complete.
The return value must be a null-terminated string.
Input: Namespace and name of function.
Output: Description of the function.
Remarks: Returns the description of function. The Custom Functions API calls
destroy string to free the allocated memory.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
IUNICHAR * getDescriptionEcho(IUNICHAR* ns, IUNICHAR* sFuncName)
{
static IUNICHAR *uniDesc = NULL;
const char *description = "Echoes the input";
if (uniDesc)
return uniDesc;
int i, len;
len = strlen(description);
uniDesc = new IUNICHAR[2*len+2];
for (i=0; i<len; i++)
{
uniDesc[i] = description[i];
}
uniDesc[i] = 0;
return uniDesc;
}
/***************************************************************************
Function: INFA_EXPR_getPrototypeEcho
Description: Gets the arguments of the ECHO function in the Expression
Editor. It calls destroyString to delete the arguments from memory when
usage is complete. The return value must be a null-terminated string. The
function returns NULL if there is no value for the arguments.
Input: Namespace and name of the function.
Output: Prototype of the function
Remarks: Returns the prototype of function. The Custom Functions API calls
destroy string to free the allocated memory.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
IUNICHAR * getPrototypeEcho(IUNICHAR* ns, IUNICHAR* sFuncName)
{
static IUNICHAR *uniProt = NULL;
const char *prototype = "Echo(x), where x can be any type, returns x";
if (uniProt)
return uniProt;
int i, len;
len = strlen(prototype);
uniProt = new IUNICHAR[2*len+2];
for (i=0; i<len; i++)
{
uniProt[i] = prototype[i];
}
uniProt[i] = 0;
return uniProt;
}
/***************************************************************************
Function: validateFunctionEcho
Description: Validates the arguments in the ECHO function. Provides the
name, datatype, precision, and scale of the arguments in the ECHO function.
Provides the datatype of the return value of the ECHO function. PowerCenter
calls this function once for each instance of the ECHO function used in a
mapping or workflow. Returns ISUCCESS when function usage is valid as per
the syntax.
The ECHO function takes exactly one argument of any datatype. The return
datatype is the same as the input datatype, because the function echoes the
input. Otherwise, returns IFAILURE.
Input: Namespace and name of the function, the number of arguments being
passed, and the metadata (datatype, scale, precision) of each argument.
Output: retValue. Set the metadata for return type.
Remarks: Called by the Custom Functions API to validate the usage of the
function and the input argument metadata to be passed. The plug-in needs
to verify the number of arguments for this function, the expected metadata
for each argument, etc. The plug-in can optionally change the expected datatype
of the input arguments. The plug-in needs to set the return type metadata.
The plugin can specify if the return value of this function is constant,
depending on whether or not all input arguments are constant.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS validateFunctionEcho(IUNICHAR* ns, IUNICHAR* sFuncName,
IUINT32 numArgs,
INFA_EXPR_OPD_METADATA** inputArgList,
INFA_EXPR_OPD_METADATA* retValue)
{
INFA_EXPR_STATUS exprStatus;
// Check number of arguments.
if (numArgs != 1)
{
static const char *err = "Echo function takes one argument.";
IUNICHAR *errMsg = NULL;
unsigned int len = strlen(err);
errMsg = new IUNICHAR[2*len+2];
unsigned int i;
for (i=0; i<len; i++)
{
errMsg[i] = err[i];
}
errMsg[i] = 0;
exprStatus.status = IFAILURE;
exprStatus.errMsg = errMsg;
return exprStatus;
}
// This is an echo function.
// It returns the input value.
retValue->datatype = inputArgList[0]->datatype;
retValue->precision = inputArgList[0]->precision;
retValue->scale = inputArgList[0]->scale;
// If the input value is constant,
// the return value is also constant.
if (inputArgList[0]->isValueConstant)
retValue->isValueConstant = ITRUE;
else
retValue->isValueConstant = IFALSE;
exprStatus.status = ISUCCESS;
return exprStatus;
}
/***************************************************************************
Function: processRowEcho
Description: Called when an input row is available to an ECHO function
instance. The data for the input arguments of the ECHO function is bound and
accessed through fnInstance-inputOPDHandles. Set the data, length, and
indicator for the output and return ports in fnInstance->retHandle.
PowerCenter calls the function-level initialization function before calling
this function.
Returns INFA_ROWSUCCESS when the function successfully processes the row of
data. Returns INFA_ROWERROR when the function encounters an error for the row
of data. The Integration Service increments the internal error count.
Only returns this value when the data access mode is row. Returns
INFA_FATALERROR when the function encounters a fatal error for the row of
data or the block of data. The Integration Service fails the session.
Input: Function instance handle, which has the input data.
Output: return value
Remarks: The plug-in needs to get various input arguments from the function
instance handle, perform calculations, and set the return value.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_ROWSTATUS processRowEcho(INFA_EXPR_FUNCTION_INSTANCE_HANDLE *fnInstance, IUNICHAR **errMsg)
{
INFA_EXPR_OPD_RUNTIME_HANDLE* arg1 = fnInstance->inputOPDHandles[0];
INFA_EXPR_OPD_RUNTIME_HANDLE* retHandle = fnInstance->retHandle;
// Check if the input argument has a null indicator.
// If yes, the return value is also null.
if (INFA_EXPR_GetIndicator(arg1) == INFA_EXPR_NULL_DATA)
{
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_NULL_DATA);
return INFA_EXPR_SUCCESS;
}
short sval;
long lval;
int ival;
char *strval;
IUNICHAR *ustrval;
void *rawval;
float fval;
double dval;
INFA_EXPR_DATE *infaDate = NULL;
int len;
// Depending on the datatype,
// get the input argument
// and set the same value in the return value.
// Also, set the same indicator.
switch (arg1->pOPDMetadata->datatype)
{
case eCTYPE_SHORT:
sval = INFA_EXPR_GetShort(arg1);
INFA_EXPR_SetShort(retHandle, sval);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_LONG:
case eCTYPE_LONG64:
lval = INFA_EXPR_GetLong(arg1);
INFA_EXPR_SetLong(retHandle, lval);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_INT32:
ival = INFA_EXPR_GetInt(arg1);
INFA_EXPR_SetInt(retHandle, ival);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_CHAR:
strval = INFA_EXPR_GetString(arg1);
len = INFA_EXPR_GetLength(arg1);
strcpy((char *)retHandle->pUserDefinedPtr, strval);
INFA_EXPR_SetString(retHandle, retHandle->pUserDefinedPtr);
INFA_EXPR_SetLength(retHandle, INFA_EXPR_GetLength(arg1));
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_RAW:
rawval = INFA_EXPR_GetRaw(arg1);
len = INFA_EXPR_GetLength(arg1);
memcpy(retHandle->pUserDefinedPtr, rawval, len);
INFA_EXPR_SetRaw(retHandle, retHandle->pUserDefinedPtr);
INFA_EXPR_SetLength(retHandle, len);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_UNICHAR:
ustrval = INFA_EXPR_GetUniString(arg1);
len = INFA_EXPR_GetLength(arg1);
memcpy(retHandle->pUserDefinedPtr, ustrval, 2*(len+1));
INFA_EXPR_SetUniString(retHandle, retHandle->pUserDefinedPtr);
INFA_EXPR_SetLength(retHandle, len);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_TIME:
infaDate = INFA_EXPR_GetDate(arg1);
*((INFA_EXPR_DATE *)retHandle->pUserDefinedPtr) = *infaDate;
INFA_EXPR_SetDate(retHandle, retHandle->pUserDefinedPtr);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_FLOAT:
fval = INFA_EXPR_GetFloat(arg1);
INFA_EXPR_SetFloat(retHandle, fval);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
case eCTYPE_DOUBLE:
dval = INFA_EXPR_GetDouble(arg1);
INFA_EXPR_SetDouble(retHandle, dval);
INFA_EXPR_SetIndicator(retHandle, INFA_EXPR_GetIndicator(arg1));
break;
default:
return INFA_EXPR_ROWERROR;
break;
}
return INFA_EXPR_SUCCESS;
}
/***************************************************************************
Function: moduleInitEcho
Description: Called once for each module to initialize any global data
structure in the function. Called before calling any function-level
functions. Returns ISUCCESS when module initialization is successful.
Otherwise, returns IFAILURE.
Input: module handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time
initialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS moduleInitEcho(INFA_EXPR_MODULE_HANDLE *modHandle)
{
INFA_EXPR_STATUS exprStatus;
// initialize the ECHO_STR
const char *fnName = "Echo";
int len = strlen(fnName);
int i;
for (i=0;i<len;i++)
ECHO_STR[i] = fnName[i];
exprStatus.status = ISUCCESS;
return exprStatus;
}
/***************************************************************************
Function: moduleDeinitEcho
Description: Called once for each module to deinitialize any data structure
in this function. Called after all function-level interactions are complete.
Returns ISUCCESS when module deinitialization is successful. Otherwise,
returns IFAILURE.
Input: module handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time
deinitialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS moduleDeinitEcho(INFA_EXPR_MODULE_HANDLE *modHandle)
{
INFA_EXPR_STATUS exprStatus;
exprStatus.status = ISUCCESS;
return exprStatus;
}
/***************************************************************************
Function: functionInitEcho
Description: Called once for each custom function to initialize any
structure related to the custom function. Module-level initialization
function is called before this function. Returns ISUCCESS when function
init is successful. Otherwise, returns IFAILURE.
Input: function handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time function
initialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS functionInitEcho(INFA_EXPR_FUNCTION_HANDLE *funHandle)
{
INFA_EXPR_STATUS exprStatus;
exprStatus.status = ISUCCESS;
return exprStatus;
}
/***************************************************************************
Function: functionDeinitEcho
Description: Called once for each function level to deinitialize any
structure related to the ECHO function. Returns ISUCCESS when function deinit
is successful. Otherwise, returns IFAILURE.
Input: function handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time function
deinitialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS functionDeinitEcho(INFA_EXPR_FUNCTION_HANDLE *funHandle)
{
INFA_EXPR_STATUS exprStatus;
exprStatus.status = ISUCCESS;
return exprStatus;
}
/***************************************************************************
Function: functionInstInitEcho
Description: Called once for each custom function instance to initialize
any structure related to the an instance of the ECHO function. If there are
two instances of ECHO in a mapping or workflow, PowerCenter calls this
function twice. PowerCenter calls the module-level initialization function
before calling this function. Returns ISUCCESS when function instance
initialization is successful. Otherwise, returns IFAILURE.
Input: function instance handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time
function instance initialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC
INFA_EXPR_STATUS functionInstInitEcho(INFA_EXPR_FUNCTION_INSTANCE_HANDLE *funInstHandle)
{
INFA_EXPR_STATUS exprStatus;
exprStatus.status = ISUCCESS;
INFA_EXPR_OPD_RUNTIME_HANDLE *retHandle = funInstHandle->retHandle;
// Allocate memory depending on the datatype.
if (retHandle->pOPDMetadata->datatype == eCTYPE_CHAR)
retHandle->pUserDefinedPtr = new char[retHandle->pOPDMetadata->precision+1];
else if (retHandle->pOPDMetadata->datatype == eCTYPE_UNICHAR)
retHandle->pUserDefinedPtr = new IUNICHAR[retHandle->pOPDMetadata->precision+1];
else if (retHandle->pOPDMetadata->datatype == eCTYPE_RAW)
retHandle->pUserDefinedPtr = new unsigned char[retHandle->pOPDMetadata->precision];
else if (retHandle->pOPDMetadata->datatype == eCTYPE_TIME)
retHandle->pUserDefinedPtr = new INFA_EXPR_DATE();
return exprStatus;
}
/***************************************************************************
Function: functionInstDeinitEcho
Description: Called once for each function level during deinitialization.
Can deinitialize any structure related to the ECHO function. Returns ISUCCESS
when deinitialization is successful. Otherwise, returns IFAILURE.
Input: function instance handle
Output: status
Remarks: The plug-in can optionally implement this method for one-time
function instance deinitialization.
***************************************************************************/
extern "C" SAMPLE_EXPR_SPEC INFA_EXPR_STATUS functionInstDeinitEcho(INFA_EXPR_FUNCTION_INSTANCE_HANDLE *funInstHandle)
{
INFA_EXPR_STATUS exprStatus;
exprStatus.status = ISUCCESS;
INFA_EXPR_OPD_RUNTIME_HANDLE *retHandle = funInstHandle->retHandle;
if (retHandle->pOPDMetadata->datatype == eCTYPE_CHAR)
delete [] (char *)retHandle->pUserDefinedPtr;
else if (retHandle->pOPDMetadata->datatype == eCTYPE_UNICHAR)
delete [] (IUNICHAR *)retHandle->pUserDefinedPtr;
else if (retHandle->pOPDMetadata->datatype == eCTYPE_RAW)
delete [] (unsigned char *)retHandle->pUserDefinedPtr;
else if (retHandle->pOPDMetadata->datatype == eCTYPE_TIME)
delete (INFA_EXPR_DATE *)retHandle->pUserDefinedPtr;
return exprStatus;
}
/***************************************************************************
Function: pushdownFunctionEcho
Description: Method to generate SQL code for pushdown optimization.
Input: Namespace and name of the function, the number of arguments being passed,
and the metadata (datatype, scale, precision) of each argument, database type,
Pushdown mode.
Output: Generated SQL.
Remarks: The plug-in can optionally implement this method to enable pushdown
optimization.
***************************************************************************/
//method to generate SQL code for pushdown optimization
extern "C" SAMPLE_EXPR_SPEC INFA_EXPR_STATUS pushdownFunctionEcho(IUNICHAR* sNameSpace,
IUNICHAR* sFuncName,
IUINT32 numArgs,
INFA_EXPR_OPD_METADATA** inputArgList,
EDatabaseType dbType,
EPushdownMode pushdownMode,
IUNICHAR** sGenSql)
{
INFA_EXPR_STATUS retStatus;
static const char *sql_str = "{1}";
// Construct the SQL: "{1}"
unsigned int len = strlen(sql_str);
IUNICHAR *pGenSql = new IUNICHAR[len+1];
unsigned int i;
for (i=0; i<len; i++)
{
pGenSql[i] = sql_str[i];
}
pGenSql[len] = 0;
// Return the generated SQL
*sGenSql = pGenSql;
retStatus.status = ISUCCESS;
retStatus.errMsg = NULL;
return retStatus;
}