In the Union example, use the following code:
/**************************************************************************
* Custom Transformation p_union Procedure File
*
* This file contains code that functions that will be called by the main
* server executable.
*
* for more information on these files,
* see $(INFA_HOME)/ExtProc/include/Readme.txt
**************************************************************************/
/*
* INFORMATICA 'UNION DEMO' developed using the API for custom
* transformations.
* File Name: p_Union.c
*
* An example of a custom transformation ('Union') using PowerCenter
*
* The purpose of the 'Union' transformation is to combine pipelines with the
* same row definition into one pipeline (i.e. union of multiple pipelines).
* [ Note that it does not correspond to the mathematical definition of union
* since it does not eliminate duplicate rows.]
*
* This example union transformation allows N input pipelines ( each
* corresponding to an input group) to be combined into one pipeline.
*
* To use this transformation in a mapping, the following attributes must be
* true:
* a. The transformation must have >= 2 input groups and only one output group.
* b. In the Properties tab set the following properties:
* i. Module Identifier: UnionDemo
* ii. Function Identifier: Union
* iii. Inputs May Block: Unchecked
* iv. Is Active: Checked
* v. Update Strategy Transformation: Unchecked *
* vi. Transformation Scope: All
* vii. Generate Transaction: Unchecked *
*
* * This version of the union transformation does not provide code for
* changing the update strategy or for generating transactions.
* c. The input groups and the output group must have the same number of ports
* and the same datatypes. This is verified in the initialization of the
* module and the session is failed if this is not true.
* d. The transformation can be used in multiple number of times in a Target
* Load Order Group and can also be contained within multiple partitions.
*
*/
/**************************************************************************
Includes
**************************************************************************/
include <stdlib.h>
#include "p_union.h"
/**************************************************************************
Forward Declarations
**************************************************************************/
INFA_STATUS validateProperties(const INFA_CT_PARTITION_HANDLE* partition);
/**************************************************************************
Functions
**************************************************************************/
/**************************************************************************
Function: p_union_procInit
Description: Initialization for the procedure. Returns INFA_SUCCESS if
procedure initialization succeeds, else return INFA_FAILURE.
Input: procedure - the handle for the procedure
Output: None
Remarks: This function will get called once for the session at
initialization time. It will be called after the moduleInit function.
**************************************************************************/
INFA_STATUS p_union_procInit( INFA_CT_PROCEDURE_HANDLE procedure)
{
const INFA_CT_TRANSFORMATION_HANDLE* transformation = NULL;
const INFA_CT_PARTITION_HANDLE* partition = NULL;
size_t nTransformations = 0, nPartitions = 0, i = 0;
/* Log a message indicating beginning of the procedure initialization */
INFA_CTLogMessageM( eESL_LOG,
"union_demo: Procedure initialization started ..." );
INFA_CTChangeStringMode( procedure, eASM_MBCS );
/* Get the transformation handles */
transformation = INFA_CTGetChildrenHandles( procedure,
&nTransformations,
TRANSFORMATIONTYPE);
/* For each transformation verify that the 0th partition has the correct
* properties. This does not need to be done for all partitions since rest
* of the partitions have the same information */
for (i = 0; i < nTransformations; i++)
{
/* Get the partition handle */
partition = INFA_CTGetChildrenHandles(transformation[i],
&nPartitions, PARTITIONTYPE );
if (validateProperties(partition) != INFA_SUCCESS)
{
INFA_CTLogMessageM( eESL_ERROR,
"union_demo: Failed to validate attributes of "
"the transformation");
return INFA_FAILURE;
}
}
INFA_CTLogMessageM( eESL_LOG,
"union_demo: Procedure initialization completed." );
return INFA_SUCCESS;
}
/**************************************************************************
Function: p_union_procDeinit
Description: Deinitialization for the procedure. Returns INFA_SUCCESS if
procedure deinitialization succeeds, else return INFA_FAILURE.
Input: procedure - the handle for the procedure
Output: None
Remarks: This function will get called once for the session at
deinitialization time. It will be called before the moduleDeinit
function.
**************************************************************************/
INFA_STATUS p_union_procDeinit( INFA_CT_PROCEDURE_HANDLE procedure,
INFA_STATUS sessionStatus )
{
/* Do nothing ... */
return INFA_SUCCESS;
}
/**************************************************************************
Function: p_union_partitionInit
Description: Initialization for the partition. Returns INFA_SUCCESS if
partition deinitialization succeeds, else return INFA_FAILURE.
Input: partition - the handle for the partition
Output: None
Remarks: This function will get called once for each partition for each
transformation in the session.
**************************************************************************/
INFA_STATUS p_union_partitionInit( INFA_CT_PARTITION_HANDLE partition )
{
/* Do nothing ... */
return INFA_SUCCESS;
}
/**************************************************************************
Function: p_union_partitionDeinit
Description: Deinitialization for the partition. Returns INFA_SUCCESS if
partition deinitialization succeeds, else return INFA_FAILURE.
Input: partition - the handle for the partition
Output: None
Remarks: This function will get called once for each partition for each
transformation in the session.
**************************************************************************/
INFA_STATUS p_union_partitionDeinit( INFA_CT_PARTITION_HANDLE partition )
{
/* Do nothing ... */
return INFA_SUCCESS;
}
/**************************************************************************
Function: p_union_inputRowNotification
Description: Notification that a row needs to be processed for an input
group in a transformation for the given partition. Returns INFA_ROWSUCCESS
if the input row was processed successfully, INFA_ROWFAILURE if the input
row was not processed successfully and INFA_FATALERROR if the input row
causes the session to fail.
Input: partition - the handle for the partition for the given row
group - the handle for the input group for the given row
Output: None
Remarks: This function is probably where the meat of your code will go,
as it is called for every row that gets sent into your transformation.
**************************************************************************/
INFA_ROWSTATUS p_union_inputRowNotification( INFA_CT_PARTITION_HANDLE partition,
INFA_CT_INPUTGROUP_HANDLE inputGroup )
{
const INFA_CT_OUTPUTGROUP_HANDLE* outputGroups = NULL;
const INFA_CT_INPUTPORT_HANDLE* inputGroupPorts = NULL;
const INFA_CT_OUTPUTPORT_HANDLE* outputGroupPorts = NULL;
size_t nNumInputPorts = 0, nNumOutputGroups = 0,
nNumPortsInOutputGroup = 0, i = 0;
/* Get the output group port handles */
outputGroups = INFA_CTGetChildrenHandles(partition,
&nNumOutputGroups,
OUTPUTGROUPTYPE);
outputGroupPorts = INFA_CTGetChildrenHandles(outputGroups[0],
&nNumPortsInOutputGroup,
OUTPUTPORTTYPE);
/* Get the input groups port handles */
inputGroupPorts = INFA_CTGetChildrenHandles(inputGroup,
&nNumInputPorts,
INPUTPORTTYPE);
/* For the union transformation, on receiving a row of input, we need to
* output that row on the output group. */
for (i = 0; i < nNumInputPorts; i++)
{
INFA_CTSetData(outputGroupPorts[i],
INFA_CTGetDataVoid(inputGroupPorts[i]));
INFA_CTSetIndicator(outputGroupPorts[i],
INFA_CTGetIndicator(inputGroupPorts[i]) );
INFA_CTSetLength(outputGroupPorts[i],
INFA_CTGetLength(inputGroupPorts[i]) );
}
/* We know there is only one output group for each partition */
return INFA_CTOutputNotification(outputGroups[0]);
}
/**************************************************************************
Function: p_union_eofNotification
Description: Notification that the last row for an input group has already
been seen. Return INFA_FAILURE if the session should fail as a result of
seeing this notification, INFA_SUCCESS otherwise.
Input: partition - the handle for the partition for the notification
group - the handle for the input group for the notification
Output: None
**************************************************************************/
INFA_STATUS p_union_eofNotification( INFA_CT_PARTITION_HANDLE partition,
INFA_CT_INPUTGROUP_HANDLE group)
{
INFA_CTLogMessageM( eESL_LOG,
"union_demo: An input group received an EOF notification");
return INFA_SUCCESS;
}
/**************************************************************************
Function: p_union_dataBdryNotification
Description: Notification that a transaction has ended. The data
boundary type can either be commit or rollback.
Return INFA_FAILURE if the session should fail as a result of
seeing this notification, INFA_SUCCESS otherwise.
Input: partition - the handle for the partition for the notification
transactionType - commit or rollback
Output: None
**************************************************************************/
INFA_STATUS p_union_dataBdryNotification ( INFA_CT_PARTITION_HANDLE partition,
INFA_CT_DATABDRY_TYPE transactionType)
{
/* Do nothing */
return INFA_SUCCESS;
}
/* Helper functions */
/**************************************************************************
Function: validateProperties
Description: Validate that the transformation has all properties expected
by a union transformation, such as at least one input group, and only
one output group. Return INFA_FAILURE if the session should fail since the
transformation was invalid, INFA_SUCCESS otherwise.
Input: partition - the handle for the partition
Output: None
**************************************************************************/
INFA_STATUS validateProperties(const INFA_CT_PARTITION_HANDLE* partition)
{
const INFA_CT_INPUTGROUP_HANDLE* inputGroups = NULL;
const INFA_CT_OUTPUTGROUP_HANDLE* outputGroups = NULL;
size_t nNumInputGroups = 0, nNumOutputGroups = 0;
const INFA_CT_INPUTPORT_HANDLE** allInputGroupsPorts = NULL;
const INFA_CT_OUTPUTPORT_HANDLE* outputGroupPorts = NULL;
size_t nNumPortsInOutputGroup = 0;
size_t i = 0, nTempNumInputPorts = 0;
/* Get the input and output group handles */
inputGroups = INFA_CTGetChildrenHandles(partition[0],
&nNumInputGroups,
INPUTGROUPTYPE);
outputGroups = INFA_CTGetChildrenHandles(partition[0],
&nNumOutputGroups,
OUTPUTGROUPTYPE);
/* 1. Number of input groups must be >= 2 and number of output groups must
* be equal to one. */
if (nNumInputGroups < 1 || nNumOutputGroups != 1)
{
INFA_CTLogMessageM( eESL_ERROR,
"UnionDemo: There must be at least two input groups "
"and only one output group");
return INFA_FAILURE;
}
/* 2. Verify that the same number of ports are in each group (including
* output group). */
outputGroupPorts = INFA_CTGetChildrenHandles(outputGroups[0],
&nNumPortsInOutputGroup,
OUTPUTPORTTYPE);
/* Allocate an array for all input groups ports */
allInputGroupsPorts = malloc(sizeof(INFA_CT_INPUTPORT_HANDLE*) *
nNumInputGroups);
for (i = 0; i < nNumInputGroups; i++)
{
allInputGroupsPorts[i] = INFA_CTGetChildrenHandles(inputGroups[i],
&nTempNumInputPorts,
INPUTPORTTYPE);
if ( nNumPortsInOutputGroup != nTempNumInputPorts)
{
INFA_CTLogMessageM( eESL_ERROR,
"UnionDemo: The number of ports in all input and "
"the output group must be the same.");
return INFA_FAILURE;
}
}
free(allInputGroupsPorts);
/* 3. Datatypes of ports in input group 1 must match data types of all other
* groups.
TODO:*/
return INFA_SUCCESS;
}