Limited supportBMC provides limited support for this version of the product. As a result, BMC no longer accepts comments in this space. If you encounter problems with the product version or the space, contact BMC Support.BMC recommends upgrading to the latest version of the product. To see documentation for that version, see UNLOAD PLUS for DB2 13.1.

Sample C user exit


This topic provides a sample user exit that is written in C.

 /*********************************************************************
 *     I D E N T I F I C A T I O N   AND   D E S C R I P T I O N      *
 **********************************************************************
 *                                                                    *
 * PGM:         ADUEXIC                                               *
 *                                                                    *
 * Description: Example BMC UNLOAD user exit                          *
 *                                                                    *
 *              Please review documentation at the end of this member *
 *                                                                    *
 * Note that all non-standard C headers are included at the front of  *
 * this code.                                                         *
 *                                                                    *
 *********************************************************************/

   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>

/*-----------------------------------------------------*/
/* #include 'aduxith0.h'      prototypes and #defines  */
/*-----------------------------------------------------*/

#define ADU_MVS

 /*
 * defines
 */

   #ifdef ADU_MSC
     #define __asm
     #define _BYREF
   #else
     #define _BYREF @
   #endif

 /*
 * prototypes
 */

  __asm void aduxitr1(int,struct LVAREA*);

/*--------------------------------------------*/
/* #include 'aduxith1.h'      aduexitp        */
/*--------------------------------------------*/

#if !defined(_XL2)
#define _XL2
typedef struct
  {
  #ifdef ADU_MVS
  unsigned BF : 16;
  #else
  unsigned BF1 : 8;
  unsigned BF2 : 8;
  #endif
  } XL2;
#endif

#if !defined(_CL100)
#define _CL100
typedef char CL100(|100|);
#endif


struct ADUEXITP
  {
/*********************************************************************/
/* ADUEXITP DEFINES THE UNLOAD USER EXIT PARM BLOCK                  */
/* YOU MAY NOT MODIFY THE FIELDS IN FRONT OF THE USER AREA           */
/* (ACTUALLY YOU MAY, BUT YOU WON'T LIKE WHAT HAPPENS)               */
/*********************************************************************/
  int xpfunc;             /* 0 = PROCESS, 1 = INIT, 2=TERMINATE      */
  void *xpsqldaA_;        /* A(SQLDA) FOR THIS TABLE                 */
  void *xptableA_;        /* A(TABLE NAME BEING UNLOADED)            */
/*    THE ABOVE POINTS TO 128 BYTE CREATOR, FOLLOWED BY 128 BYTE NAME*/
  char xpflags;           /* VARIOUS FLAGS                           */
#define XPFDEBUG 0x01     /* DEBUG IS ON                             */
  char _f0;               /*                                         */
  short xprefP_;          /* BLOCK REFERENCE #                       */
  void *xpssidA_;         /* A(SSID)                         4  BYTES*/
  void *xpuserA_;         /* A(USERID)                       8  BYTES*/
  void *xputidA_;         /* A(UTILITY ID)                   16 BYTES*/
  int _f1(|6|);           /*                                         */
/*                                                                   */
/*                  * USER AREA                                      */
/*                                                                   */
/*XPUSRMSG CONTAINS A SINGLE MESSAGE ENTRY.  ON RETURN FROM THE EXIT,*/
/*            IF THIS FIELD IS NON-BLANK, IT IS PRINTED THEN BLANKED.*/
/*                                                                   */
/* XPUSRMS@ POINTS TO A MESSAGE BUFFER THAT CAN CONTAIN MULTIPLE EXIT*/
/*                MESSAGES OF EQUAL LENGTH.  THESE MESSAGE(S) WILL BE*/
/*                            PRINTED AFTER XPUSRMSG (IF ANY).       */
/*                   FORMAT OF THE MESSAGE BUFFER AT THIS ADDRESS IS:*/
/*                                                                   */
/*               #MSGS   DS  H          NUMBER OF LINES, 0 = NO PRINT*/
/*               MSGSIZE DS  H          SIZE OF EACH LINE (MAX = 100)*/
/*                       MSGTEXT DS  CL(#MSGS*MSGSIZE)  USER MESSAGES*/
/*                                                                   */
  void *xpuserwA_;        /* USER WORK AREA ADDRESS                  */
  int xpuserf1;           /* USER FIELD                              */
  int xpuserf2;           /* USER FIELD                              */
  int xpuserf3;           /* USER FIELD                              */
  int xpuserf4;           /* USER FIELD                              */
  void *xpusermA_;        /* USER MESSAGE BUFFER ADDRESS             */
  int xpusermz;           /* USER MESSAGE BUFFER TOTAL SIZE          */
  CL100 xpusrmsg;         /* USER SINGLE MESSAGE AREA                */
/*                                                                   */
  XL2 xpresrv;            /* RESERVED                             V12*/
/*                                                                   */
  char xpusrpad(|842|);   /* PADDING                                 */
#define XPK 1024          /*                                         */
  };


#define XPFLAGS                         xpflags
#define XPFUNC                          xpfunc
#define XPREFP_                         xprefP_
#define XPRESRV                         xpresrv
#define XPSQLDAA_                       xpsqldaA_
#define XPSSIDA_                        xpssidA_
#define XPTABLEA_                       xptableA_
#define XPUSERA_                        xpuserA_
#define XPUSERF1                        xpuserf1
#define XPUSERF2                        xpuserf2
#define XPUSERF3                        xpuserf3
#define XPUSERF4                        xpuserf4
#define xpusermz                        xpusermz
#define XPUSERMA_                       xpusermA_
#define XPUSERWA_                       xpuserwA_
#define XPUSRMSG                        xpusrmsg
#define XPUSRPAD                        xpusrpad
#define XPUTIDA_                        xputidA_


/*
SYMBOL         OFFSET     SIZE     TYPE      C-TYPE       C-NAME
ADUEXITP       000000    000000
XPFLAGS        00000C    000001    X         char         xpflags
XPFUNC         000000    000004    F         int          xpfunc
XPREF#         00000E    000002    H         short        xprefP_
XPRESRV        0000B4    000002    XL2       XL2          xpresrv
XPSQLDA@       000004    000004    A         void *       xpsqldaA_
XPSSID@        000010    000004    A         void *       xpssidA_
XPTABLE@       000008    000004    A         void *       xptableA_
XPUSER@        000014    000004    A         void *       xpuserA_
XPUSERF1       000038    000004    F         int          xpuserf1
XPUSERF2       00003C    000004    F         int          xpuserf2
XPUSERF3       000040    000004    F         int          xpuserf3
XPUSERF4       000044    000004    F         int          xpuserf4
XPUSERMZ       00004C    000004    F         int          xpusermz
XPUSERM@       000048    000004    A         void *       xpusermA_
XPUSERW@       000034    000004    A         void *       xpuserwA_
XPUSRMSG       000050    000064    CL100     CL100        xpusrmsg
XPUSRPAD       0000B6    00034A    (1024-... char (|842|) xpusrpad
XPUTID@        000018    000004    A         void *       xputidA_
*/

/*-----------------------------------------*/
/* #include 'aduxith2.h'      lvarea       */
/*-----------------------------------------*/

#if !defined(_XL292)
#define _XL292
typedef char XL292(|292|);
#endif

#if !defined(_CL128)
#define _CL128
typedef char CL128(|128|);
#endif

#if !defined(_CL8)
#define _CL8
typedef char CL8(|8|);
#endif

#if !defined(_CL6)
#define _CL6
typedef char CL6(|6|);
#endif

#if !defined(_PL2)
#define _PL2
typedef struct
  {
  #ifdef ADU_MVS
  unsigned BF :16;
  #else
  unsigned BF1 :8;
  unsigned BF2 :8;
  #endif
  } PL2;
#endif


struct LVAREA
  {
/*********************************************************************/
/* LOCAL VARIABLES WORK AREA DSECT                                   */
/*********************************************************************/
  int lvsave(|18|);       /* LOCAL SAVE AREA                         */
  PL2 lvkeepP_;           /* RECORDS KEPT                            */
  PL2 lvdiscP_;           /* RECORDS DISCARDED                       */
#define LVBLANKA 76       /* START OF BLANKING AREA                  */
  CL6 lvkeep;             /* UNPKED KEEPERS                          */
  CL6 lvdisc;             /* UNPKED DISCARDS                         */
  CL128 lvtbcrea;           /* TABLE CREATOR                           */
  CL128 lvtbname;          /* TABLE NAME                              */
#define LVBLANKZ 38       /* SIZE OF BLANKING AREA                   */
  XL292 lvspares;         /*                                         */
#define LVAREAZ 406       /*                                         */
  };


#define LVDISC                          lvdisc
#define LVDISCP_                        lvdiscP_
#define LVKEEP                          lvkeep
#define LVKEEPP_                        lvkeepP_
#define LVSAVE                          lvsave
#define LVSPARES                        lvspares
#define LVTBCREA                        lvtbcrea
#define LVTBNAME                        lvtbname


/*
SYMBOL         OFFSET     SIZE     TYPE      C-TYPE       C-NAME
LVAREA         000000    000000
LVDISC         000052    000006    CL6       CL6          lvdisc
LVDISC#        00004A    000002    PL2       PL2          lvdiscP_
LVKEEP         00004C    000006    CL6       CL6          lvkeep
LVKEEP#        000048    000002    PL2       PL2          lvkeepP_
LVSAVE         000000    000048    18F       int (|18|)   lvsave
LVSPARES       000072    000124    XL292     XL292        lvspares
LVTBCREA       000058    000008    CL128     CL128        lvtbcrea
LVTBNAME       000060    000012    CL128     CL128        lvtbname
*/

/*---------------------------------------*/
/* #include 'aduxith3.h'   SQLDA Header  */
/*---------------------------------------*/

#if !defined(_CL8)
#define _CL8
typedef char CL8(|8|);
#endif


struct SQLDA
  {
  CL8 sqldaid;            /* ID                                      */
  int sqldabc;            /* BYTE COUNT                              */
  short sqln;             /* TOTAL VARS                              */
  short sqld;             /* PERTINENT VARS                          */
  int sqlvar(|0|);        /* BEGIN VARS                              */
#define SQLDSIZ 16        /* SIZE OF FIXED PART                      */
  };


#define SQLD                            sqld
#define SQLDABC                         sqldabc
#define SQLDAID                         sqldaid
#define SQLN                            sqln
#define SQLVAR                          sqlvar(|0|)


/*
SYMBOL         OFFSET     SIZE     TYPE      C-TYPE       C-NAME
SQLD           00000E    000002    H         short        sqld
SQLDA          000000    000000
SQLDABC        000008    000004    F         int          sqldabc
SQLDAID        000000    000008    CL8       CL8          sqldaid
SQLN           00000C    000002    H         short        sqln
SQLVAR         000010    000000    0F        int (|0|)    sqlvar
*/

/*---------------------------------------------*/
/* #include 'aduxith4.h'  SQLVARN HEADER START */
/*---------------------------------------------*/

#if !defined(_CL30)
#define _CL30
typedef char CL30(|30|);
#endif


struct SQLVARN
  {
  short sqltype;          /* TYPE CODE     */
  #ifdef ADU_MVS
  short sqllen(|0|);      /* NAME LENGTH   */
  #else
  short sqllen;
  #endif
  char sqlprcsn;          /* DEC PRECISION */
  char sqlscale;          /* DEC SCALE     */
  void *sqldata;          /* ADDR OF VAR   */
  void *sqlind;           /* ADDR OF IND   */
  union
    {
    struct
      {
      short sqlname;      /* DESCRIBE NAME */
      CL30 _f0;           /*               */
      } _s0;
    struct
      {
      short sqlnamz;      /* SIZEOF COLNAME*/
      CL30 sqlnam;        /* NAME ALONE    */
#define SQLVSIZ 44        /*               */
      } _s1;
    };
  };

/*--------------------*/
/* end SQLVARN HEADER */
/*--------------------*/

#define SQLDATA                         sqldata
#define SQLIND                          sqlind
#define SQLLEN                          sqllen(|0|)
#define SQLNAM                          _s1.sqlnam
#define sqlnamz                         _s1.sqlnamz
#define SQLNAME                         _s0.sqlname
#define SQLPRCSN                        sqlprcsn
#define SQLSCALE                        sqlscale
#define SQLTYPE                         sqltype


/*
SYMBOL         OFFSET     SIZE     TYPE      C-TYPE       C-NAME
SQLDATA        000004    000004    A         void *       sqldata
SQLIND         000008    000004    A         void *       sqlind
SQLLEN         000002    000000    0H        short (|0|)  sqllen
SQLNAM         00000E    00001E    CL30      CL30         _s1.sqlnam
sqlnamz        00000C    000002    H         short        _s1.sqlnamz
SQLNAME        00000C    000002    H         short        _s0.sqlname
SQLPRCSN       000002    000001    X         char         sqlprcsn
SQLSCALE       000003    000001    X         char         sqlscale
SQLTYPE        000000    000002    H         short        sqltype
SQLVARN        000000    000000
*/

   static int BadFuncCode(struct ADUEXITP *pzAduexitp);

   #define MAXFUNC 2
   #define PROCESS 0
   #define INITIAL 1
   #define CLEANUP 2

   static char
      szAccept   (||) = 'ACCEPTED'
     ,szDiscard  (||) = 'DISCARDED'
     ,szMbadfunc (||) = 'BAD FUNCTION CODE RECEIVED FROM MAIN'
     ,szMgetmerr (||) = 'GETMAIN ERROR GETTING USER STORAGE'
     ,szMgetmer2 (||) = 'GETMAIN ERROR GETTING MSG STORAGE'
     ,szIgot2ini (||) = 'COLUMNS AVAILABLE FROM TABLE'
     ,szIgot2pro (||) = 'PROCESSING REGISTRATION ID:'
     ,szIgot2cln (||) = 'PROCESSING IS COMPLETED'
     ;

 int aduexic( long lFcode ,struct ADUEXITP *pzAduexitp ){

   int lRc;

 /*---------------------*
 *   Main Entry Point   *
 *---------------------*/

   lRc = 0;

   switch(lFcode){

     case PROCESS:
       lRc = Process(pzAduexitp);
       break;

     case INITIAL:
       lRc = Initial(pzAduexitp);
       break;

     case CLEANUP:
       lRc = Cleanup(pzAduexitp);
       break;

     default:
       return BadFuncCode(pzAduexitp);
   }

   return lRc;
 }

 /*-------------------------------------------------------------------*
 *                                                                    *
 *                         INTERNAL ROUTINES                          *
 *                       INTERNAL  .  ROUTINES                        *
 *                     INTERNAL  .....  ROUTINES                      *
 *                       INTERNAL  .  ROUTINES                        *
 *                         INTERNAL ROUTINES                          *
 *                                                                    *
 *-------------------------------------------------------------------*/

 /*------------------------------------*
 * handle bad function call            *
 *------------------------------------*/
 static int BadFuncCode(struct ADUEXITP *pzAduexitp){
   memset(pzAduexitp->XPUSRMSG ,' ' ,sizeof(pzAduexitp->XPUSRMSG));
   memcpy(pzAduexitp->XPUSRMSG ,szMbadfunc ,sizeof(szMbadfunc));
   return 8;
 }

 /*------------------------------------*
 * Processing call                     *
 *------------------------------------*/
 static int Process(struct ADUEXITP *pzAduexitp){

   short sCols;
   char *pstrMsg;
   struct SQLDA *pzSqlda;
   struct SQLVARN *pzSqlvarn;

   if ( (pstrMsg=pzAduexitp->XPUSERMA_)!=NULL ){
     *(short*)pstrMsg = 0;
   }

   /* Say I got here */

   memcpy(pzAduexitp->XPUSRMSG ,szIgot2pro ,sizeof(szIgot2pro));

   pzSqlda = pzAduexitp->XPSQLDAA_;
   sCols = pzSqlda->SQLN;
   pzSqlvarn = (struct SQLVARN*)( ((char*)pzSqlda)+SQLDSIZ);

   while(sCols){
     if ( memcmp(pzSqlvarn->SQLNAM ,'REGISTRATION' ,12)==0 ){
       memcpy(pzAduexitp->XPUSRMSG+sizeof(szIgot2pro)
       ,pzSqlvarn->SQLDATA
       ,8);
       if ( (memcmp(pzSqlvarn->SQLDATA ,'NCC-1700' ,8)>=0)
       && (memcmp(pzSqlvarn->SQLDATA ,'NCC-1711' ,8)<=0) ){

         /* We're starting over with columns */

         sCols = pzSqlda->SQLN;
         pzSqlvarn = (struct SQLVARN*)( ((char*)pzSqlda)+SQLDSIZ);
         while(sCols){
           if (memcmp(pzSqlvarn->SQLNAM,'NAME ',5)==0){
             if ( (pzSqlvarn->SQLIND == NULL)
             || ((pzSqlvarn->SQLIND != NULL)
                && (*((char*)pzSqlvarn->SQLIND)=='?')) ){
               memcpy(pzAduexitp->XPUSRMSG
               +sizeof(pzAduexitp->XPUSRMSG)-21
               ,'STARSHIP NAME IS NULL'
               ,21);
               return 4;   /* Q U I T ! */
             } else {
               aduxitr1(2,pzAduexitp->XPUSERWA_); /* bump keep count */
               return 0;  /* Q U I T ! */
             }
           }
           pzSqlvarn++;
           sCols--;
         }
         memcpy(pzAduexitp->XPUSRMSG ,'NAME COLUMN NOT FOUND' ,21);
         return 8;   /* Q U I T ! */
       } else {
         aduxitr1(1,pzAduexitp->XPUSERWA_); /* bump discard count */
         memcpy(pzAduexitp->XPUSRMSG
          +sizeof(pzAduexitp->XPUSRMSG)
          -sizeof(szDiscard)
          ,szDiscard
          ,sizeof(szDiscard));
         return 4;   /* Q U I T ! */
       }
     }
     pzSqlvarn++;
     sCols--;
   }
   memcpy(pzAduexitp->XPUSRMSG ,'REGISTRATION COLUMN NOT FOUND' ,29);
   return 8;     /* Q U I T ! */

 }


 /*------------------------*
 *   Exit Initialization   *
 *------------------------*/

 static int Initial(struct ADUEXITP *pzAduexitp){

   short sCols, sMsgs;
   char *pstrMsg;
   struct LVAREA *pzLvarea;
   struct SQLDA *pzSqlda;
   struct SQLVARN *pzSqlvarn;

   struct TBNAME {
      char strCreator (|8|)  ;
      char strName    (|18|) ;
   } *pzTb;


   if ( memcmp(pzAduexitp->XPUTIDA_ ,'JST' ,3) != 0){
     return 4;
   } else if (memcmp(((char*)pzAduexitp->XPTABLEA_)+8
          ,'STARSHIP' ,8) != 0){
     return 4;
   }

   /* allocate user workarea */

   if ( (pzLvarea=calloc(1,LVAREAZ))==NULL){
     return GetmainError(1,pzAduexitp);
   }

   pzAduexitp->XPUSERWA_ = pzLvarea; /* remember for use later */

   aduxitr1(0,pzLvarea);
   memset(pzLvarea->LVKEEP ,' ' ,sizeof(LVBLANKZ));

   pzTb = pzAduexitp->XPTABLEA_;
   memcpy(pzLvarea->LVTBCREA ,pzTb->strCreator ,sizeof(pzLvarea->LVTBCREA));
   memcpy(pzLvarea->LVTBNAME ,pzTb->strName    ,sizeof(pzLvarea->LVTBNAME));

   /* Say I am here, and have this table */

   memcpy(pzAduexitp->XPUSRMSG ,szIgot2ini ,sizeof(szIgot2ini));
   memcpy(pzAduexitp->XPUSRMSG+sizeof(szIgot2ini)
    ,pzAduexitp->XPTABLEA_
    ,sizeof(struct TBNAME));

   pzSqlda = pzAduexitp->XPSQLDAA_;
   sMsgs = pzSqlda->SQLN * sizeof(pzAduexitp->XPUSRMSG);
   sMsgs += 4+256;   /* adjust for prefix and pad */
   pzAduexitp->xpusermz = (int)sMsgs;
   if ( (pzAduexitp->XPUSERMA_=calloc(1,sMsgs))==NULL){
     return GetmainError(2,pzAduexitp);
   }

   sCols = pzSqlda->SQLN;
   pzSqlvarn = (struct SQLVARN*)( ((char*)pzSqlda)+SQLDSIZ);

   pstrMsg = pzAduexitp->XPUSERMA_;
   pstrMsg += 4;
   sMsgs = 0;
   while(sCols){
     memset(pstrMsg ,' ' ,sizeof(pzAduexitp->XPUSRMSG));
     memcpy(pstrMsg ,pzSqlvarn->SQLNAM ,sizeof(pzSqlvarn->SQLNAM));
     sMsgs++;
     pstrMsg += sizeof(pzAduexitp->XPUSRMSG);
     pzSqlvarn++;
     sCols--;
   }
   /*
   memcpy(pzAduexitp->XPUSERMA_ ,&sMsgs ,sizeof(sMsgs));
   */
   *((short*)pzAduexitp->XPUSERMA_) = sMsgs;
   *(((short*)pzAduexitp->XPUSERMA_)+1) = sizeof(pzAduexitp->XPUSRMSG);

   return 0;
 }


 /*--------------------------------*
 *   Exit termination processing   *
 *--------------------------------*/

 static int Cleanup(struct ADUEXITP *pzAduexitp){

   short sMsgs;
   char *pstrMsg;
   struct LVAREA *pzLvarea;

   pzLvarea = pzAduexitp->XPUSERWA_;

   memcpy(pzAduexitp->XPUSRMSG ,szIgot2cln ,sizeof(szIgot2cln));
   sMsgs = 0;
   pstrMsg = pzAduexitp->XPUSERMA_;
   pstrMsg += 4;   /* bump past gunk */

   aduxitr1(3,pzAduexitp->XPUSERWA_); /* unpack counts  */

   memset(pstrMsg ,' ' ,sizeof(pzAduexitp->XPUSRMSG));
   memcpy(pstrMsg ,pzLvarea->LVDISC ,sizeof(pzLvarea->LVDISC));
   memcpy(pstrMsg+sizeof(pzLvarea->LVDISC)+1
    ,'DID NOT QUALIFY AS HEAVY CRUISERS'
    ,33);
   pstrMsg += sizeof(pzAduexitp->XPUSRMSG);
   sMsgs++;

   memset(pstrMsg ,' ' ,sizeof(pzAduexitp->XPUSRMSG));
   memcpy(pstrMsg ,pzLvarea->LVKEEP ,sizeof(pzLvarea->LVKEEP));
   memcpy(pstrMsg+sizeof(pzLvarea->LVKEEP)+1
    ,'QUALIFIED AS HEAVY CRUISERS'
    ,27);
   pstrMsg += sizeof(pzAduexitp->XPUSRMSG);
   sMsgs++;

   memset(pstrMsg ,' ' ,sizeof(pzAduexitp->XPUSRMSG));
   memcpy(pstrMsg+sizeof(pzLvarea->LVKEEP)+1
    ,'** ALL HEAVY CRUISERS NOW UNLOADED **'
    ,37);

   *((short*)pzAduexitp->XPUSERMA_) = sMsgs;

   /* free message block if we acquired one */

   if (pzAduexitp->XPUSERMA_ != NULL){
     free(pzAduexitp->XPUSERMA_);
     pzAduexitp->XPUSERMA_ = NULL;
   }

   /* free main workarea */

   free(pzAduexitp->XPUSERWA_);
   pzAduexitp->XPUSERWA_ = NULL;

   return 0;
 }

 /*-------------------------------------*
 *   Error in acquiring local storage   *
 *-------------------------------------*/

 static int GetmainError(int lType ,struct ADUEXITP *pzAduexitp){

   memset(pzAduexitp->XPUSRMSG ,' ' ,sizeof(pzAduexitp->XPUSRMSG));

   if (lType == 1){
     memcpy(pzAduexitp->XPUSRMSG ,szMgetmerr ,sizeof(szMgetmerr));
   } else {
     memcpy(pzAduexitp->XPUSRMSG ,szMgetmer2 ,sizeof(szMgetmer2));
   }

   return 8;
 }


/*
***************************
*   D I S C L A I M E R   *
***************************

   This is a sample UNLOAD PLUS user exit written in SAS C.

   This exit would be used in order to inspect and/or manipulate unload
   data records prior to their being written to the sort or output
   dataset.

   This exit will only be invoked when it is specifically named
   in the 'UNLOADEXIT ADUEXIC C' parameter.

   Note: please review the documentation in the reference manual,
   and the following usage notes prior to implementing this exit.

   please call BMC Product Support with any questions you may
   have in this area.

     Phone: 1-800-841-2031    outside Texas
     1-713-240-8800    in Texas


*******************************
*   E X I T S C E N A R I O   *
*******************************

  As always it is tough to come up with a good example for an exit
  that is intended to be application oriented. For the purposes of
  this example, a DB2 table exists containing data on Federation
  starships.

  The DB2 table name is STARSHIP, containing the following columns:

    REGISTRATION CHAR(16) NOT NULL,
    NAME VARCHAR(64))

  The purpose of this exit is to screen the starships by registration
  number to filter out any non-heavy cruiser class starships.

  In the star fleet, there were 12 heavy cruiser class starships
  with registration numbers between NCC-1700 and NCC-1711.
  This code only allows these records to be unloaded.
  (This filtering could be done with unload control statements, but
   since this data would appear on a report that could be stolen by
   the Romulans, starfleet feels it is more secure to hide the logic
   for selection in a program)

  In addition, this screening is only done if the unload utility id
  begins with the characters 'JST'.

  The name must also be checked to ensure that it is not null since
  this is a nullable field (clerical errors do occur occaisionally!)

  the bottom line of all this is that this example shows how to:

  1. Inspect the user exit block and pseudo SQLDA
  2. Getmain storage needed that is preserved during the unload
  3. Getmain storage for multiple user messages
  4. Issue single and multiple messages for DB2 UNLOAD PLUS to issue
  5. Find and look at unload table column names
  6. Find and inspect data prior to being unloaded
  7. Determine null fields
  8. Print records being processed with messages
  9. Accept and discard records from UNLOAD PLUS processing

*****************
*   N O T E S   *
*****************

  ADUEXIC is called at 3 points in processing a table unload.

  When invoked, r0 contains a function code.

  r1 contains the address of a user exit block described by the
  ADUEXITP dsect copied to your program from macro member @aduxprm.
  fields for your use in this block are described in the dsect.

  The main field of interest is the pseudo-sqlda pointer xpsqlda@
  which points to an 'sqlda' prepared for each selected unload table.
  this sqlda has the same format and contents of a db2 sqlda, with the
  main exception being that the descriptions of the data fields are
  the output descriptions (after conversions if any), and the data
  pointers are pointing to the output record offsets in the record
  about to be written (function call 0 only).

  function:

     Function code 0 = process record

     this call is made after a record is prepared for writing.
     all fields are converted ready for output.  the sqlda
     provides the field types and record positions of the data.

     return codes from process:

         0 = accept this record
         4 = discard this record
         anything else = terminate the run.


     Function code 1 = initialization call

     this call is made during table unload initialization.  it
     happens once per table to be unloaded to allow selection of
     whether or not to process the table with the exit.

     return codes from initialize:

         0 = activate exit for records from this table
         4 = don't use the exit for this table.
         anything else = terminate the run.


     Function code 2 = termination/cleanup call

     this call is made just prior to termination of the unload,
     to allow you to perform any cleanup functions necessary.

     return codes for terminate are ignored.


    for any exit function, the exit may insert message text in the
    message area for printing upon return.


*/

 

 

Tip: For faster searching, add an asterisk to the end of your partial query. Example: cert*