Example field procedure program that masks data

Add field procedure FP1 to column C1. The field procedure FP1 expects an additional parameter which it uses to indicate a version level for the field procedure.

ALTER TABLE TESTTAB ALTER C1 SET FIELDPROC FP1(1)


#include "string.h"
#include <QSYSINC/H/SQLFP>
void reverse(char *in, char *out, long length);
main(int argc, void *argv[])
{
    short *funccode = argv[1];
    sqlfpFieldProcedureParameterList_T *optionalParms = argv[2];
    char *sqlstate = argv[7];
    sqlfpMessageText_T *msgtext = argv[8];
    int version;
    sqlfpOptionalParameterValueDescriptor_T *optionalParmPtr;
    sqlfpInformation_T *info = argv[9];
    int masked;
    if (optionalParms->sqlfpNumberOfOptionalParms != 1)
    {
	memcpy(sqlstate,"38001",5);
	return;
    }
    optionalParmPtr = (void *)&(optionalParms->sqlfpParmList);
    version = *((int *)&optionalParmPtr->sqlfpParmData);
    /*******************************************************************/
    /* CREATE CALL                                                     */
    /*******************************************************************/
    if (*funccode == 8) /* create time */
    {
	sqlfpParameterDescription_T *inDataType = argv[3];
	sqlfpParameterDescription_T *outDataType = argv[5];
	if (inDataType->sqlfpSqlType !=452 &&
	    inDataType->sqlfpSqlType !=453 ) /* only support fixed length char */
	{
	    memcpy(sqlstate,"38002",5);
	    return;
	}
        /* an example of how an optional parm could be used             */
        /* In this case it is used to add version support if it is      */
        /* expected that the fieldproc program may support multiple     */
        /* versions                                                     */
	if (version != 1) /* only support version 1 at this time */
	{
	    memcpy(sqlstate,"38003",5);
	    return;
	}

	/* do something here to determine the result data type */
	/* ..... */
	/* in this example input and output types are exactly the same */
	/* so just copy */
	memcpy(outDataType, inDataType, sizeof(sqlfpParameterDescription_T));
    }
    /*******************************************************************/
    /* ENCODE (WRITE) CALL                                             */
    /*******************************************************************/
    else if (*funccode == 0) /* encode */
    {
	sqlfpParameterDescription_T *decodedDataType = argv[3];
	char *decodedData = argv[4];
	char *encodedData = argv[6];
	/* Detect that the value passed on encode is masked. */
	/* Return 09501 to tell DB that: */
	/* - The field should not be updated for an update operation */
	/* - The default value should be used for an insert operation*/
	if ( memcmp(decodedData, "XXXXXXXXXXXX", 12) == 0 )
	{
	    memcpy(sqlstate,"09501",5);
	}
	else
	{
	    reverse(decodedData, encodedData, decodedDataType->sqlfpByteLength);
	}
    }
    /*******************************************************************/
    /* DECODE (READ) CALL                                              */
    /*******************************************************************/
    else if (*funccode == 4) /* decode */
    {
	char *decodedData = argv[4];
	sqlfpParameterDescription_T *encodedDataType = argv[5];
	char *encodedData = argv[6];
	/* The 9th paramter indicates that the column must not be */
	/* masked. For example, during ALTER TABLE or RGZPFM. */
	if ( info->sqlfpNoMask == '1' )
	{
	    reverse(encodedData, decodedData, encodedDataType->sqlfpByteLength);
	    return;
	}
	else
	{
	    reverse(encodedData, decodedData, encodedDataType->sqlfpByteLength);
	    /* Mask the data when appropriate */
	    /* Assume mask is set to 0 when it should not be masked */
	    /* and 1 when it shoulbe be masked */
	    if (masked == 1)
	    {
		memcpy(decodedData, "XXXXXXXXXXXX",
		       encodedDataType->sqlfpByteLength);
	    }
	}
	return;
    }
    /*******************************************************************/
    /* ERROR- UNSUPPORTED OPTION                                       */
    /*******************************************************************/
    else /* unsupported option -- error */
	memcpy(sqlstate, "38003",5);
}
/*******************************************************************/
/* REVERSE                                                         */
/*******************************************************************/
void reverse(char *in, char *out, long length)
{
    int i;
    for (i=0;i<length; ++i) {
	out[length - (i+1)] = in[i];
    }
}