Example field procedure program that masks data

Add field procedure FP1 to column C1. The Field Procedure FP1 takes one additional parameter which indicates the number of bytes of the column the field procedure should operate on.

ALTER TABLE TESTTAB ALTER C1 SET FIELDPROC FP1(10)

#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 bytesToProcess;
  sqlfpOptionalParameterValueDescriptor_T *optionalParmPtr;
  sqlfpInformation_T *info = argv[9]; 
  int masked;

   if (optionalParms->sqlfpNumberOfOptionalParms != 1)
   {
      memcpy(sqlstate,"38001",5);
      return;
   }
   optionalParmPtr = (void *)&(optionalParms->sqlfpParmList);
   bytesToProcess = *((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;
      }
      /* 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 */
   {
      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, bytesToProcess);
      }
   }

/*******************************************************************/ 
/* DECODE (READ) CALL                                              */ 
/*******************************************************************/ 
   else if (*funccode == 4)    /* decode */
   {
     char *decodedData = argv[4];
     char *encodedData = argv[6];

     /* The 9th paramter indicates that the column must not be     */
     /* masked. For exmaple, during ALTER TABLE or RGZPFM.         */
     if ( info->sqlfpNoMask == '1' )
     {
       reverse(encodedData, decodedData, bytesToProcess);
       return;
     }

     else
     {
       reverse(encodedData, decodedData, bytesToProcess);
       /* 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", 12);
       }
     }

     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]; 
    }
}