Example C program that calls a stored procedure

You can call the C language version of the GETPRML stored procedure that uses the GENERAL WITH NULLS linkage convention.

Because the stored procedure returns result sets, this program checks for result sets and retrieves the contents of the result sets. The following figure contains the example C program that calls the GETPRML stored procedure.

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 main()
 {
   /************************************************************/
   /* Include the SQLCA and SQLDA                              */
   /************************************************************/
   EXEC SQL INCLUDE SQLCA;
   EXEC SQL INCLUDE SQLDA;   
   /************************************************************/
   /* Declare variables that are not SQL-related.              */
   /************************************************************/
   short int i;                /* Loop counter                 */
   /************************************************************/
   /* Declare the following:                                   */
   /* - Parameters used to call stored procedure GETPRML       */
   /* - An SQLDA for DESCRIBE PROCEDURE                        */
   /* - An SQLDA for DESCRIBE CURSOR                           */
   /* - Result set variable locators for up to three result    */
   /*   sets                                                   */
   /************************************************************/
   EXEC SQL BEGIN DECLARE SECTION;
     char procnm[19];          /* INPUT parm -- PROCEDURE name */
     char schema[9];           /* INPUT parm -- User's schema  */
     long int out_code;        /* OUTPUT -- SQLCODE from the   */
                               /*   SELECT operation.          */
     char parmlst[255];        /* OUTPUT -- RUNOPTS values     */
                               /*   for the matching row in    */
                               /*   catalog table SYSROUTINES  */
     struct indicators {
       short int procnm_ind;
       short int schema_ind;
       short int out_code_ind;
       short int parmlst_ind;
       } parmind;
                               /* Indicator variable structure */
 
     struct sqlda *proc_da;
                               /* SQLDA for DESCRIBE PROCEDURE */
     struct sqlda *res_da;
                               /* SQLDA for DESCRIBE CURSOR    */
     static volatile
       SQL TYPE IS RESULT_SET_LOCATOR *loc1, *loc2, *loc3;
                               /* Locator variables            */
   EXEC SQL END DECLARE SECTION;
 
  /*************************************************************/
  /* Allocate the SQLDAs to be used for DESCRIBE               */
  /* PROCEDURE and DESCRIBE CURSOR.  Assume that at most       */
  /* three cursors are returned and that each result set       */
  /* has no more than five columns.                            */
  /*************************************************************/
  proc_da = (struct sqlda *)malloc(SQLDASIZE(3));
  res_da = (struct sqlda *)malloc(SQLDASIZE(5));
 
   /************************************************************/
   /* Call the GETPRML stored procedure to retrieve the        */
   /* RUNOPTS values for the stored procedure.   In this       */
   /* example, we request the PARMLIST definition for the      */
   /* stored procedure named DSN8EP2.                          */
   /*                                                          */
   /* The call should complete with SQLCODE +466 because       */
   /* GETPRML returns result sets.                             */
   /************************************************************/
   strcpy(procnm,"dsn8ep2           ");
                 /* Input parameter -- PROCEDURE to be found   */
   strcpy(schema,"        ");
                 /* Input parameter -- Schema name for proc    */
   parmind.procnm_ind=0;
   parmind.schema_ind=0;
   parmind.out_code_ind=0;
                 /* Indicate that none of the input parameters */
                 /* have null values                           */
   parmind.parmlst_ind=-1;
                 /* The parmlst parameter is an output parm.   */
                 /* Mark PARMLST parameter as null, so the DB2 */
                 /* requester does not have to send the entire  */
                 /* PARMLST variable to the server.  This      */
                 /* helps reduce network I/O time, because     */
                 /* PARMLST is fairly large.                   */
   EXEC SQL
     CALL GETPRML(:procnm INDICATOR :parmind.procnm_ind,
                  :schema INDICATOR :parmind.schema_ind,
                  :out_code INDICATOR :parmind.out_code_ind,
                  :parmlst INDICATOR :parmind.parmlst_ind);
   if(SQLCODE!=+466)          /* If SQL CALL failed,           */
   {
                              /*   print the SQLCODE and any   */
                              /*   message tokens              */
       printf("SQL CALL failed due to SQLCODE = %d\n",
                    sqlca.sqlcode);
       printf("sqlca.sqlerrmc = ");
       for(i=0;i<sqlca.sqlerrml;i++)
         printf("%c",sqlca.sqlerrmc[i]);
       printf("\n");
   }
   else                       /* If the CALL worked,           */
     if(out_code!=0)          /* Did GETPRML hit an error?     */
       printf("GETPRML failed due to RC = %d\n", out_code); 
     /**********************************************************/
     /* If everything worked, do the following:                */
     /* - Print out the parameters returned.                   */
     /* - Retrieve the result sets returned.                   */
     /**********************************************************/
     else
     {
       printf("RUNOPTS = %s\n", parmlst);
                              /* Print out the runopts list    */
 
       /********************************************************/
       /* Use the statement DESCRIBE PROCEDURE to              */
       /* return information about the result sets in the      */
       /* SQLDA pointed to by proc_da:                         */
       /* - SQLD contains the number of result sets that were  */
       /*   returned by the stored procedure.                  */
       /* - Each SQLVAR entry has the following information    */
       /*   about a result set:                                */
       /*   - SQLNAME contains the name of the cursor that     */
       /*     the stored procedure uses to return the result   */
       /*     set.                                             */
       /*   - SQLIND contains an estimate of the number of     */
       /*     rows in the result set.                          */
       /*   - SQLDATA contains the result locator value for    */
       /*     the result set.                                  */
       /********************************************************/
       EXEC SQL DESCRIBE PROCEDURE INTO :*proc_da;
       /********************************************************/
       /* Assume that you have examined SQLD and determined    */
       /* that there is one result set.  Use the statement     */
       /* ASSOCIATE LOCATORS to establish a result set locator */
       /* for the result set.                                  */
       /********************************************************/
       EXEC SQL ASSOCIATE LOCATORS (:loc1) WITH PROCEDURE GETPRML;
 
       /********************************************************/
       /* Use the statement ALLOCATE CURSOR to associate a     */
       /* cursor for the result set.                           */
       /********************************************************/
       EXEC SQL ALLOCATE C1 CURSOR FOR RESULT SET :loc1;
       /********************************************************/
       /* Use the statement DESCRIBE CURSOR to determine the   */
       /* columns in the result set.                           */
       /********************************************************/
       EXEC SQL DESCRIBE CURSOR C1 INTO :*res_da;
 
       /********************************************************/
       /* Call a routine (not shown here) to do the following: */
       /* - Allocate a buffer for data and indicator values    */
       /*   fetched from the result table.                     */
       /* - Update the SQLDATA and SQLIND fields in each       */
       /*   SQLVAR of *res_da with the addresses at which to   */
       /*   to put the fetched data and values of indicator    */
       /*   variables.                                         */
       /********************************************************/
       alloc_outbuff(res_da);
 
       /********************************************************/
       /* Fetch the data from the result table.                */
       /********************************************************/
       while(SQLCODE==0)
         EXEC SQL FETCH C1 USING DESCRIPTOR :*res_da;
     }
   return;
 }