DSN8DUWF

Returns weather information for various cities, as read from the data set passed as the argument to input para- meter 'weatherDSN'.

 /********************************************************************* 00000100
 * Module name = DSN8DUWF (DB2 sample program)                        * 00000200
 *                                                                    * 00000300
 * DESCRIPTIVE NAME = Weather (DB2 user-defined table function)       * 00000400
 *                                                                    * 00000500
 *     5675-DB2                                                       * 00000600
 *     (C) COPYRIGHT 1998, 2000 IBM CORP.                             * 00000700
 *                                                                    * 00000800
 *     STATUS = VERSION 7                                             * 00000900
 *                                                                    * 00001000
 * Function: Returns weather information for various cities, as read  * 00001100
 *           from the data set passed as the argument to input para-  * 00001200
 *           meter 'weatherDSN'.  The data includes the name of a     * 00001300
 *           city followed by its weather information: Temperature in * 00001400
 *           fahrenheit, percent humidity, wind direction, wind velo- * 00001500
 *           city, barometric pressure, and the forecast.  See the    * 00001600
 *           structure 'weatherRec' for the record format.            * 00001700
 *                                                                    * 00001800
 *           File pointer information is retained between calls in    * 00001900
 *           the UDF scratchpad area.                                 * 00002000
 *                                                                    * 00002100
 *           Data read from the input data set is returned by this    * 00002200
 *           function as a DB2 table with the following structure:    * 00002300
 *           with this structure:                                     * 00002400
 *                                                                    * 00002500
 *           CITY          VARCHAR(30),                               * 00002600
 *           TEMP_IN_F     INTEGER,                                   * 00002700
 *           HUMIDITY      INTEGER,                                   * 00002800
 *           WIND          VARCHAR(5),                                * 00002900
 *           WIND_VELOCITY INTEGER,                                   * 00003000
 *           BAROMETER     FLOAT,                                     * 00003100
 *           FORECAST      VARCHAR(25)                                * 00003200
 *                                                                    * 00003300
 *           Clients invoking this function can use standard SQL      * 00003400
 *           syntax to create a desired result set.                   * 00003500
 *                                                                    * 00003600
 *           Example invocation:                                      * 00003700
 *                                                                    * 00003800
 *           EXEC SQL DECLARE  WEATHER_CURSOR                         * 00003900
 *                     CURSOR  FOR                                    * 00004000
 *                     SELECT  CITY,                                  * 00004100
 *                             FORECAST                               * 00004200
 *                       FROM  TABLE( DSN8.WEATHER(:hvWeatherDSN) )   * 00004300
 *                         AS  W                                      * 00004400
 *                      WHERE  CITY = 'Juneau, AK';                   * 00004500
 *                                                                    * 00004600
 * Notes:                                                             * 00004700
 *   Dependencies: Requires IBM C/C++ for OS/390 V1R3 or higher       * 00004800
 *                                                                    * 00004900
 *   Restrictions:                                                    * 00005000
 *                                                                    * 00005100
 * Module type: C program                                             * 00005200
 *   Processor: IBM C/C++ for OS/390 V1R3 or higher                   * 00005300
 * Module size: See linkedit output                                   * 00005400
 *  Attributes: Re-entrant and re-usable                              * 00005500
 *                                                                    * 00005600
 * Entry Point: DSN8DUWF                                              * 00005700
 *     Purpose: See Function                                          * 00005800
 *     Linkage: DB2SQL                                                * 00005900
 *              Invoked via SQL UDF call                              * 00006000
 *                                                                    * 00006100
 *                                                                    * 00006200
 *       Input: Parameters explicitly passed to this function:        * 00006300
 *              - *weatherDSN  : pointer to a char[45], null-termi-   * 00006400
 *                               nated string having the name of the  * 00006500
 *                               source data for the weather reports. * 00006600
 *              - *niWeatherDSN: pointer to a short integer having    * 00006700
 *                               the null indicator variable for      * 00006800
 *                               *weatherDSN.                         * 00006900
 *              - *fnName      : pointer to a char[138], null-termi-  * 00007000
 *                               nated string having the UDF family   * 00007100
 *                               name of this function.               * 00007200
 *              - *specificName: pointer to a char[129], null-termi-  * 00007300
 *                               nated string having the UDF specific * 00007400
 *                               name of this function.               * 00007500
 *                                                                    * 00007600
 *                                                                    * 00007700
 *      Output: Parameters explicitly passed by this function:        * 00007800
 *              - *city        : pointer to a char[31], null-termi-   * 00007900
 *                               nated string to receive the name of  * 00008000
 *                               the city.                            * 00008100
 *              - *temp_in_f   : pointer to a long integer to receive * 00008200
 *                               the temperature in fahrenheit for    * 00008300
 *                               the city.                            * 00008400
 *              - *humidity    : pointer to a long integer to receive * 00008500
 *                               the percent humidity for the city.   * 00008600
 *              - *wind        : pointer to a char[6], null-termi-    * 00008700
 *                               nated string to receive the wind di- * 00008800
 *                               rection for the city.                * 00008900
 *              - *wind_velocity: pointer to a long integer to receive* 00009000
 *                               the wind velocity for city.          * 00009100
 *              - *barometer   : pointer to a double word to receive  * 00009200
 *                               the barometric pressure for the city.* 00009300
 *              - *forecast    : pointer to a char[26], null-termi-   * 00009400
 *                               nated string to receive the forecast * 00009500
 *                               for the city.                        * 00009600
 *              - *niCity      : pointer to a short integer to re-    * 00009700
 *                               ceive the null indicator variable    * 00009800
 *                               for *city.                           * 00009900
 *              - *niTemp_in_f : pointer to a short integer to re-    * 00010000
 *                               ceive the null indicator variable    * 00010100
 *                               for *temp_in_f.                      * 00010200
 *              - *niHumidity  : pointer to a short integer to re-    * 00010300
 *                               ceive the null indicator variable    * 00010400
 *                               for *humidity.                       * 00010500
 *              - *niWind      : pointer to a short integer to re-    * 00010600
 *                               ceive the null indicator variable    * 00010700
 *                               for *wind.                           * 00010800
 *              - *niWind_velocity: pointer to a short integer to re- * 00010900
 *                               ceive the null indicator variable    * 00011000
 *                               for *wind_velocity.                  * 00011100
 *              - *niBarometer : pointer to a short integer to re-    * 00011200
 *                               ceive the null indicator variable    * 00011300
 *                               for *barometer.                      * 00011400
 *              - *niForecast  : pointer to a short integer to re-    * 00011500
 *                               ceive the null indicator variable    * 00011600
 *                               for *forecast.                       * 00011700
 *              - *sqlstate    : pointer to a char[06], null-termi-   * 00011800
 *                               nated string to receive the SQLSTATE.* 00011900
 *              - *message     : pointer to a char[70], null-termi-   * 00012000
 *                               nated string to receive a diagnostic * 00012100
 *                               message if one is generated by this  * 00012200
 *                               function.                            * 00012300
 *                                                                    * 00012400
 * Normal Exit: Return Code: SQLSTATE = 00000                         * 00012500
 *              - Message: none                                       * 00012600
 *                                                                    * 00012700
 *              Return Code: SQLSTATE = 02000 (end of input)          * 00012800
 *              - Message: none                                       * 00012900
 *                                                                    * 00013000
 *  Error Exit: Return Code: SQLSTATE = 38601                         * 00013100
 *              - Message: DSN8DUWF Error: Unable to allocate DD      * 00013200
 *                                         <ddname>: Error code=<x>,  * 00013300
 *                                         info code=<y>              * 00013400
 *                                                                    * 00013500
 *              Return Code: SQLSTATE = 38602                         * 00013600
 *              - Message: DSN8DUWF Error: Error opening weather data * 00013700
 *                                         set                        * 00013800
 *                                                                    * 00013900
 *              Return Code: SQLSTATE = 38603                         * 00014000
 *              - Message: DSN8DUWF Error: Error reading weather data * 00014100
 *                                         set                        * 00014200
 *                                                                    * 00014300
 *              Return Code: SQLSTATE = 38604                         * 00014400
 *              - Message: DSN8DUWF Error: Error closing weather data * 00014500
 *                                         set                        * 00014600
 *                                                                    * 00014700
 *              Return Code: SQLSTATE = 38605                         * 00014800
 *              - Message: DSN8DUWF Error: FREE failed for DDNAME <x>.* 00014900
 *                                         Error code=<y>, info code= * 00015000
 *                                         <z>                        * 00015100
 *                                                                    * 00015200
 *    External References:                                            * 00015300
 *             - Routines/Services: dyninit: IBM C/C++, dynit.h       * 00015400
 *                                  - Initializes control block for   * 00015500
 *                                    dynamic file allocation         * 00015600
 *                                  dynalloc: IBM C/C++, dynit.h      * 00015700
 *                                  - Dynamic file allocation         * 00015800
 *                                  dynfree: IBM C/C++, dynit.h       * 00015900
 *                                  - Dynamic file deallocation       * 00016000
 *             - Data areas       : None                              * 00016100
 *             - Control blocks   : __dyn_t: IBM C/C++, dynint.h      * 00016200
 *                                  - for dynamic file allocation     * 00016300
 *                                                                    * 00016400
 *  Pseudocode:                                                       * 00016500
 *   DSN8DUWF:                                                        * 00016600
 *   - If SQLUDF call type is SQLUDF_TF_FIRST (-2)                    * 00016700
 *     - call allocWeatherDSN to allocate the data set name passed as * 00016800
 *       the argument to the weatherDSN parameter                     * 00016900
 *   - Else if SQLUDF call type is SQLUDF_TF_OPEN (-1)                * 00017000
 *     - call openWeatherDS to open the weather data set              * 00017100
 *   - Else if SQLUDF call type is SQLUDF_TF_FETCH (0)                * 00017200
 *     - call readWeatherDS to read the next record from the weather  * 00017300
 *       data set                                                     * 00017400
 *     - if EOF, set sqlstate to 02000 to signal end of cursor to     * 00017500
 *       client                                                       * 00017600
 *     - else call buildReturnRow to populate the UDF table function  * 00017700
 *       output parameters with data from the input record            * 00017800
 *   - Else if SQLUDF call type is SQLUDF_TF_CLOSE (1)                * 00017900
 *     - call closeWeatherDS to close the weather data set            * 00018000
 *   - Else (SQLUDF call type is SQLUDF_TF_FINAL (2) )                * 00018100
 *     - call freeWeatherDS to deallocate the weather data set        * 00018200
 *   End DSN8DUWF                                                     * 00018300
 *                                                                    * 00018400
 *   allocWeatherDS:                                                  * 00018500
 *   - if the data set name passed in as the argument to the input    * 00018600
 *     parameter weatherDSN is for a partitioned data set, extract    * 00018700
 *     the member name                                                * 00018800
 *   - use dynalloc to dynamically allocate the data set (and member, * 00018900
 *     if applicable)                                                 * 00019000
 *   - if allocation error occurs, issue sqlstate 38601 and a diag-   * 00019100
 *     nostic message                                                 * 00019200
 *   End allocWeatherDS                                               * 00019300
 *                                                                    * 00019400
 *   openWeatherDS:                                                   * 00019500
 *   - open the weather data set                                      * 00019600
 *   - if the data cannot be opened, issue sqlstate 38602 and a diag- * 00019700
 *     nostic message                                                 * 00019800
 *   End openWeatherDS                                                * 00019900
 *                                                                    * 00020000
 *   readWeatherDS:                                                   * 00020100
 *   - read the next record from the data set                         * 00020200
 *     - this implicitly updates the file pointer variable, which is  * 00020300
 *       maintained in the UDF scratchpad area                        * 00020400
 *   - if the data set cannot be read, issue sqlstate 38603 and a     * 00020500
 *     diagnostic message                                             * 00020600
 *   End readWeatherDS                                                * 00020700
 *                                                                    * 00020800
 *   buildReturnRow:                                                  * 00020900
 *   - extract weather data fields from the weather data set          * 00021000
 *   - perform appropriate data type conversions                      * 00021100
 *   - copy the (converted) data to the appropriate output parameters * 00021200
 *   End buildReturnRow                                               * 00021300
 *                                                                    * 00021400
 *   closeWeatherDS:                                                  * 00021500
 *   - close the weather data set                                     * 00021600
 *   - if the data cannot be closed, issue sqlstate 38604 and a diag- * 00021700
 *     nostic message                                                 * 00021800
 *   End closeWeatherDS                                               * 00021900
 *                                                                    * 00022000
 *   freeWeatherDS:                                                   * 00022100
 *   - use dynfree to dynamically deallocate the weather data set     * 00022200
 *   - if deallocation error occurs, issue sqlstate 38605 and a diag- * 00022300
 *     nostic message                                                 * 00022400
 *   End freeWeatherDS                                                * 00022500
 *                                                                    * 00022600
 *********************************************************************/ 00022700
                                                                        00022800
 #pragma linkage(DSN8DUWF,fetchable)                                    00022900
                                                                        00023000
 /********************** C library definitions ***********************/ 00023100
 #include <dynit.h>                                                     00023200
 #include <stdlib.h>                                                    00023300
 #include <string.h>                                                    00023400
 #include <stdio.h>                                                     00023500
                                                                        00023600
 /***************************** Equates ******************************/ 00023700
 #define         NO             0      /* Negative                   */ 00023800
 #define         YES            1      /* Affirmative                */ 00023900
                                                                        00024000
 #define         NULLCHAR     '\0'     /* Null character             */ 00024100
                                                                        00024200
 #define         SQLUDF_TF_FIRST -2    /* First call                 */ 00024300
 #define         SQLUDF_TF_OPEN  -1    /* Open table call            */ 00024400
 #define         SQLUDF_TF_FETCH  0    /* Fetch next row call        */ 00024500
 #define         SQLUDF_TF_CLOSE  1    /* Close table call           */ 00024600
 #define         SQLUDF_TF_FINAL  2    /* Final call                 */ 00024700
                                                                        00024800
 /************************ Weather Data Set **************************/ 00024900
 struct scr                            /* Struct for scratchpad area */ 00025000
 {                                                                      00025100
   long          len;                  /* Length of scratchpad data  */ 00025200
   FILE          *WEATHRin;            /* ptr to weather data set    */ 00025300
   char          not_used[100];        /* filler                     */ 00025400
 };                                                                     00025500
                                                                        00025600
 char            WEATHRinBuffer[8188]; /* Input buffer for weather ds*/ 00025700
 short int       moreWeatherRecs = YES;/* EOF indicator, weather ds  */ 00025800
                                                                        00025900
 typedef struct                        /* Weather record structure   */ 00026000
 {                                                                      00026100
   char          cityField[30];        /* name of city         01-30 */ 00026200
   char          filler1[1];           /*                      31-31 */ 00026300
   char          temp_in_fField[3];    /* temp in fahrenheit   32-34 */ 00026400
   char          filler2[1];           /*                      35-35 */ 00026500
   char          humidityField[3];     /* percent humidity     36-38 */ 00026600
   char          filler3[1];           /*                      39-39 */ 00026700
   char          windField[5];         /* wind direction       40-44 */ 00026800
   char          filler4[1];           /*                      45-45 */ 00026900
   char          windVelocityField[3]; /* wind velocity        46-48 */ 00027000
   char          filler5[1];           /*                      49-49 */ 00027100
   char          barometerField[5];    /* baromtric pressure   50-54 */ 00027200
   char          filler6[1];           /*                      55-55 */ 00027300
   char          forecastField[25];    /* forecast             56-80 */ 00027400
 } weatherRec;                                                          00027500
                                                                        00027600
 weatherRec    *pweatherRec = (weatherRec *)&WEATHRinBuffer;            00027700
                                                                        00027800
                                                                        00027900
 /*************************** Functions ******************************/ 00028000
 void *DSN8DUWF                        /* Weather function           */ 00028100
 ( char          *weatherDSN,          /* in: input ds, weather data */ 00028200
   char          *city,                /* out: name of city          */ 00028300
   long int      *temp_in_f,           /* out: temp in fahrenheit    */ 00028400
   long int      *humidity,            /* out: relative humidity     */ 00028500
   char          *wind,                /* out: wind direction        */ 00028600
   long int      *wind_velocity,       /* out: wind velocity         */ 00028700
   double        *barometer,           /* out: barometric pressure   */ 00028800
   char          *forecast,            /* out: forecast              */ 00028900
   short int     *niWeatherDSN,        /* in: indic var, weather dsn */ 00029000
   short int     *niCity,              /* out: indic var, city name  */ 00029100
   short int     *niTemp_in_f,         /* out: indic var, temperature*/ 00029200
   short int     *niHumidity,          /* out: indic var, humidity   */ 00029300
   short int     *niWind,              /* out: indic var, wind dir   */ 00029400
   short int     *niWind_velocity,     /* out: indic var, wind veloc */ 00029500
   short int     *niBarometer,         /* out: indic var, baro press */ 00029600
   short int     *niForecast,          /* out: indic var, forecast   */ 00029700
   char          *sqlstate,            /* out: SQLSTATE              */ 00029800
   char          *fnName,              /* in: family name of function*/ 00029900
   char          *specificName,        /* in: specific name of func  */ 00030000
   char          *msgtext,             /* out: diagnostic message    */ 00030100
   struct scr    *scratchptr,          /* i/o: scratchpad area       */ 00030200
   long          *callType             /* i/o: call type parameter   */ 00030300
 );                                                                     00030400
                                                                        00030500
 void allocWeatherDS                   /* Dynam allocates weather ds */ 00030600
 ( char          *weatherDSN,          /* in: name of weather ds     */ 00030700
   char          *sqlstate,            /* out: sqlstate              */ 00030800
   char          *msgtext              /* out: diag message text     */ 00030900
 );                                                                     00031000
                                                                        00031100
 void openWeatherDS                    /* Opens weather data set     */ 00031200
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00031300
   char          *sqlstate,            /* out: sqlstate              */ 00031400
   char          *msgtext              /* out: diag message text     */ 00031500
 );                                                                     00031600
                                                                        00031700
 void readWeatherDS                    /* Reads from weather data set*/ 00031800
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00031900
   char          *sqlstate,            /* out: sqlstate              */ 00032000
   char          *msgtext              /* out: diag message text     */ 00032100
 );                                                                     00032200
                                                                        00032300
 void buildReturnRow                   /* Builds function return row */ 00032400
 ( char          *city,                /* out: name of city          */ 00032500
   long int      *temp_in_f,           /* out: temp in fahrenheit    */ 00032600
   long int      *humidity,            /* out: relative humidity     */ 00032700
   char          *wind,                /* out: wind direction        */ 00032800
   long int      *wind_velocity,       /* out: wind velocity         */ 00032900
   double        *barometer,           /* out: barometric pressure   */ 00033000
   char          *forecast,            /* out: forecast              */ 00033100
   short int     *niCity,              /* out: indic var, city name  */ 00033200
   short int     *niTemp_in_f,         /* out: indic var, temperature*/ 00033300
   short int     *niHumidity,          /* out: indic var, humidity   */ 00033400
   short int     *niWind,              /* out: indic var, wind dir   */ 00033500
   short int     *niWind_velocity,     /* out: indic var, wind veloc */ 00033600
   short int     *niBarometer,         /* out: indic var, baro press */ 00033700
   short int     *niForecast           /* out: indic var, forecast   */ 00033800
 );                                                                     00033900
                                                                        00034000
 void closeWeatherDS                   /* Closes weather data set    */ 00034100
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00034200
   char          *sqlstate,            /* out: sqlstate              */ 00034300
   char          *msgtext              /* out: diag message text     */ 00034400
 );                                                                     00034500
                                                                        00034600
 void freeWeatherDS                    /* Dynam frees the weather ds */ 00034700
 ( char          *sqlstate,            /* out: sqlstate              */ 00034800
   char          *msgtext              /* out: diag message text     */ 00034900
 );                                                                     00035000
                                                                        00035100
                                                                        00035200
 void *DSN8DUWF                                                         00035300
 ( char          *weatherDSN,          /* in: input ds, weather data */ 00035400
   char          *city,                /* out: name of city          */ 00035500
   long int      *temp_in_f,           /* out: temp in fahrenheit    */ 00035600
   long int      *humidity,            /* out: relative humidity     */ 00035700
   char          *wind,                /* out: wind direction        */ 00035800
   long int      *wind_velocity,       /* out: wind velocity         */ 00035900
   double        *barometer,           /* out: barometric pressure   */ 00036000
   char          *forecast,            /* out: forecast              */ 00036100
   short int     *niWeatherDSN,        /* in: indic var, weather dsn */ 00036200
   short int     *niCity,              /* out: indic var, city name  */ 00036300
   short int     *niTemp_in_f,         /* out: indic var, temperature*/ 00036400
   short int     *niHumidity,          /* out: indic var, humidity   */ 00036500
   short int     *niWind,              /* out: indic var, wind dir   */ 00036600
   short int     *niWind_velocity,     /* out: indic var, wind veloc */ 00036700
   short int     *niBarometer,         /* out: indic var, baro press */ 00036800
   short int     *niForecast,          /* out: indic var, forecast   */ 00036900
   char          *sqlstate,            /* out: SQLSTATE              */ 00037000
   char          *fnName,              /* in: family name of function*/ 00037100
   char          *specificName,        /* in: specific name of func  */ 00037200
   char          *msgtext,             /* out: diagnostic message    */ 00037300
   struct scr    *scratchptr,          /* i/o: scratchpad area       */ 00037400
   long          *callType             /* i/o: call type parameter   */ 00037500
 )                                                                      00037600
 /********************************************************************* 00037700
 * Main routine for Weather table function                            * 00037800
 *********************************************************************/ 00037900
 {                                                                      00038000
   /******************************************************************* 00038100
   * First call: Dynamically allocate the weather data set            * 00038200
   *******************************************************************/ 00038300
   if( *callType == SQLUDF_TF_FIRST )                                   00038400
     {                                                                  00038500
       strcpy( sqlstate,"00000" );     /* Init sqlstate return var   */ 00038600
       *msgtext  = NULLCHAR;           /* Init message text rtrn var */ 00038700
       allocWeatherDS( weatherDSN, sqlstate, msgtext );                 00038800
     }                                                                  00038900
   /******************************************************************* 00039000
   * Second call: Open the weather data set                           * 00039100
   *******************************************************************/ 00039200
   else if( *callType == SQLUDF_TF_OPEN )                               00039300
     {                                                                  00039400
       strcpy( sqlstate,"00000" );     /* Init sqlstate return var   */ 00039500
       *msgtext  = NULLCHAR;           /* Init message text rtrn var */ 00039600
       moreWeatherRecs = YES;          /* EOF indicator, weather ds  */ 00039700
       openWeatherDS( scratchptr, sqlstate, msgtext );                  00039800
     }                                                                  00039900
   /******************************************************************* 00040000
   * Subsequent calls: Read a record from the weather data set        * 00040100
   *******************************************************************/ 00040200
   else if( *callType == SQLUDF_TF_FETCH )                              00040300
     {                                                                  00040400
       readWeatherDS( scratchptr, sqlstate, msgtext );                  00040500
       if( moreWeatherRecs == NO )     /* If no more weather data    */ 00040600
         strcpy( sqlstate,"02000" );   /* ..signal for FINAL CALL    */ 00040700
       else                                                             00040800
         {                                                              00040900
           buildReturnRow( city,                                        00041000
                           temp_in_f,                                   00041100
                           humidity,                                    00041200
                           wind,                                        00041300
                           wind_velocity,                               00041400
                           barometer,                                   00041500
                           forecast,                                    00041600
                           niCity,                                      00041700
                           niTemp_in_f,                                 00041800
                           niHumidity,                                  00041900
                           niWind,                                      00042000
                           niWind_velocity,                             00042100
                           niBarometer,                                 00042200
                           niForecast );                                00042300
         }                                                              00042400
     }                                                                  00042500
   /******************************************************************* 00042600
   * End of file: Close weather data set                              * 00042700
   *******************************************************************/ 00042800
   else if( *callType == SQLUDF_TF_CLOSE )                              00042900
     {                                                                  00043000
       closeWeatherDS( scratchptr, sqlstate, msgtext );                 00043100
     }                                                                  00043200
   /******************************************************************* 00043300
   * Final call: De-allocate weather data set                         * 00043400
   *******************************************************************/ 00043500
   else /* *callType == SQLUDF_TF_FINAL */                              00043600
     {                                                                  00043700
       freeWeatherDS( sqlstate, msgtext );                              00043800
     }                                                                  00043900
   return;                                                              00044000
 }                                                                      00044100
                                                                        00044200
                                                                        00044300
 void allocWeatherDS                                                    00044400
 ( char          *weatherDSN,          /* in: name of weather ds     */ 00044500
   char          *sqlstate,            /* out: sqlstate              */ 00044600
   char          *msgtext              /* out: diag message text     */ 00044700
 )                                                                      00044800
 /********************************************************************* 00044900
 * Dynamically allocates weatherDSN to the WEATHRIN DD.  If the value * 00045000
 * in weatherDSN contains parentheses, it is assumed to specify a     * 00045100
 * partitioned data set; otherwise it is assumed to specify a         * 00045200
 * physical sequential data set.                                      * 00045300
 *********************************************************************/ 00045400
 {                                                                      00045500
   __dyn_t       ip;                   /* pointer to control block   */ 00045600
   char          DSname[45];           /* recv's copy of weather dsn */ 00045700
   char          *tokPtr;              /* string ptr for token parser*/ 00045800
                                                                        00045900
   dyninit( &ip );                     /* Initialize control block   */ 00046000
   ip.__ddname = "WEATHRIN";           /* Specify DDNAME of WEATHRIN */ 00046100
   /******************************************************************* 00046200
   * Use the strtok func to separate the PDS member name, if any,     * 00046300
   * from the data set name                                           * 00046400
   *******************************************************************/ 00046500
   strcpy( DSname,weatherDSN );        /* Get workcopy of weather dsn*/ 00046600
   tokPtr = strtok( DSname,"(" );      /* Parse for open parenthesis */ 00046700
   if( tokPtr == NULL )                /* If none found then         */ 00046800
     ip.__dsname = DSname;             /* ...data set is not a PDS   */ 00046900
   else                                /* Otherwise                  */ 00047000
     {                                                                  00047100
       ip.__dsname = tokPtr;           /* ...token is name of a PDS  */ 00047200
       tokPtr = strtok( NULL,")" );    /* ...parse for close paren   */ 00047300
       ip.__member = tokPtr;           /* ...token is name of member */ 00047400
     }                                                                  00047500
   ip.__status = __DISP_SHR;           /* Specify DISP=SHR           */ 00047600
                                                                        00047700
   /******************************************************************* 00047800
   * If dynamic allocation failed, generate an error message and quit * 00047900
   *******************************************************************/ 00048000
   if( dynalloc(&ip) != 0 )                                             00048100
     {                                                                  00048200
       sprintf( msgtext,"Unable to allocate DD %s: "                    00048300
                        "Error code=%hX, info code=%hX\n",              00048400
                ip.__ddname,                                            00048500
                ip.__errcode,                                           00048600
                ip.__infocode );                                        00048700
       strcpy( sqlstate,"38601" );                                      00048800
     }                                                                  00048900
 } /* end allocWeatherDS */                                             00049000
                                                                        00049100
                                                                        00049200
 void openWeatherDS                                                     00049300
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00049400
   char          *sqlstate,            /* out: sqlstate              */ 00049500
   char          *msgtext              /* out: diag message text     */ 00049600
 )                                                                      00049700
 /********************************************************************* 00049800
 * Opens the weather data set, which has been allocated to the DD     * 00049900
 * WEATHRIN, for record-type input, and assigns the file pointer to   * 00050000
 * the scratchpad area indicated by scratchptr.                       * 00050100
 *********************************************************************/ 00050200
 {                                                                      00050300
   scratchptr->WEATHRin = fopen("DD:WEATHRIN",                          00050400
                                "rb,recfm=vb,lrecl=8188,type=record");  00050500
                                                                        00050600
   if( scratchptr->WEATHRin == NULL )  /* If unable to open data set */ 00050700
     {                                 /* ..set return msg and state */ 00050800
       strcpy( msgtext,"Error opening weather data set" );              00050900
       strcpy( sqlstate,"38602" );                                      00051000
     }                                                                  00051100
 } /* end openWeatherDS */                                              00051200
                                                                        00051300
                                                                        00051400
 void readWeatherDS                                                     00051500
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00051600
   char          *sqlstate,            /* out: sqlstate              */ 00051700
   char          *msgtext              /* out: diag message text     */ 00051800
 )                                                                      00051900
 /********************************************************************* 00052000
 * Reads the next record from the weather data set                    * 00052100
 *********************************************************************/ 00052200
 {                                                                      00052300
   short int     recordLength = 0;     /* Receives len of current rec*/ 00052400
                                                                        00052500
   recordLength                        /*                            */ 00052600
     = fread( WEATHRinBuffer,          /* Read into WEATHRinBuffer   */ 00052700
              1,                       /* ..a record                 */ 00052800
              sizeof( WEATHRinBuffer ),/* ..<= len of WEATHRinBuffer */ 00052900
              scratchptr->WEATHRin );  /* ..from the weather data set*/ 00053000
                                                                        00053100
   if( ferror(scratchptr->WEATHRin) )  /* If an error occurs         */ 00053200
     {                                 /* ..set return msg and state */ 00053300
       strcpy( msgtext,"Error reading weather data set" );              00053400
       strcpy( sqlstate,"38603" );                                      00053500
     }                                                                  00053600
   else if( feof(scratchptr->WEATHRin))/* Else if end of file reached*/ 00053700
     moreWeatherRecs = NO;             /* ..get ready to quit        */ 00053800
 } /* end readWeatherDS */                                              00053900
                                                                        00054000
                                                                        00054100
 void buildReturnRow                   /* Builds function return row */ 00054200
 ( char          *city,                /* out: name of city          */ 00054300
   long int      *temp_in_f,           /* out: temp in fahrenheit    */ 00054400
   long int      *humidity,            /* out: relative humidity     */ 00054500
   char          *wind,                /* out: wind direction        */ 00054600
   long int      *wind_velocity,       /* out: wind velocity         */ 00054700
   double        *barometer,           /* out: barometric pressure   */ 00054800
   char          *forecast,            /* out: forecast              */ 00054900
   short int     *niCity,              /* out: indic var, city name  */ 00055000
   short int     *niTemp_in_f,         /* out: indic var, temperature*/ 00055100
   short int     *niHumidity,          /* out: indic var, humidity   */ 00055200
   short int     *niWind,              /* out: indic var, wind dir   */ 00055300
   short int     *niWind_velocity,     /* out: indic var, wind veloc */ 00055400
   short int     *niBarometer,         /* out: indic var, baro press */ 00055500
   short int     *niForecast           /* out: indic var, forecast   */ 00055600
 )                                                                      00055700
 /********************************************************************* 00055800
 * Build a return row for the current call to the WEATHER table       * 00055900
 * function.                                                          * 00056000
 *********************************************************************/ 00056100
 {                                                                      00056200
   char          workBuff[6];          /* for datatype conversions   */ 00056300
                                                                        00056400
   /******************************************************************* 00056500
   * Move the city name to its table variable                         * 00056600
   *******************************************************************/ 00056700
   strncpy( city,pweatherRec->cityField,30 );                           00056800
   *niCity = 0;                                                         00056900
                                                                        00057000
   /******************************************************************* 00057100
   * Move the temperature to its table var after making it numeric    * 00057200
   *******************************************************************/ 00057300
   memset( workBuff,'\0',6 );                                           00057400
   strncpy( workBuff,pweatherRec->temp_in_fField,3 );                   00057500
   *temp_in_f = atoi( workBuff );                                       00057600
   *niTemp_in_f = 0;                                                    00057700
                                                                        00057800
   /******************************************************************* 00057900
   * Move the humidity factor to its table var after making it numeric* 00058000
   *******************************************************************/ 00058100
   memset( workBuff,'\0',6 );                                           00058200
   strncpy( workBuff,pweatherRec->humidityField,3 );                    00058300
   *humidity = atoi( workBuff );                                        00058400
   *niHumidity = 0;                                                     00058500
                                                                        00058600
   /******************************************************************* 00058700
   * Move the wind direction to its table variable                    * 00058800
   *******************************************************************/ 00058900
   strncpy( wind,pweatherRec->windField,5 );                            00059000
   *niWind = 0;                                                         00059100
                                                                        00059200
   /******************************************************************* 00059300
   * Move the wind velocity to its table var after making it numeric  * 00059400
   *******************************************************************/ 00059500
   memset( workBuff,'\0',6 );                                           00059600
   strncpy( workBuff,pweatherRec->windVelocityField,3 );                00059700
   *wind_velocity = atoi( workBuff );                                   00059800
   *niWind_velocity = 0;                                                00059900
                                                                        00060000
   /******************************************************************* 00060100
   * Move the forecast to its table variable                          * 00060200
   *******************************************************************/ 00060300
   memset( workBuff,'\0',6 );                                           00060400
   strncpy( workBuff,pweatherRec->barometerField,5 );                   00060500
   *barometer = atof( workBuff );                                       00060600
   *niBarometer = 0;                                                    00060700
                                                                        00060800
   /******************************************************************* 00060900
   * Move the forecast to its table variable                          * 00061000
   *******************************************************************/ 00061100
   strncpy( forecast,pweatherRec->forecastField,25 );                   00061200
   *niForecast = 0;                                                     00061300
                                                                        00061400
 } /* end buildReturnRow */                                             00061500
                                                                        00061600
                                                                        00061700
 void closeWeatherDS                                                    00061800
 ( struct scr    *scratchptr,          /* in: ptr to scratch pad     */ 00061900
   char          *sqlstate,            /* out: sqlstate              */ 00062000
   char          *msgtext              /* out: diag message text     */ 00062100
 )                                                                      00062200
 /********************************************************************* 00062300
 * Closes the weather data set and resets the file pointer in the     * 00062400
 * scratchpad area.                                                   * 00062500
 *********************************************************************/ 00062600
 {                                                                      00062700
   if( fclose(scratchptr->WEATHRin) != 0 )                              00062800
                                       /* If unable to close data set*/ 00062900
     {                                 /* ..set return msg and state */ 00063000
       strcpy( msgtext,"Error closing weather data set" );              00063100
       strcpy( sqlstate,"38604" );                                      00063200
     }                                                                  00063300
   else                                                                 00063400
     scratchptr->WEATHRin = NULLCHAR; /* Otherwise, reset file ptr   */ 00063500
 } /* end closeWeatherDS */                                             00063600
                                                                        00063700
                                                                        00063800
 void freeWeatherDS                                                     00063900
 ( char          *sqlstate,            /* out: sqlstate              */ 00064000
   char          *msgtext              /* out: diag message text     */ 00064100
 )                                                                      00064200
 /********************************************************************* 00064300
 * Dynamically frees the weather data set, which has been allocated   * 00064400
 * to the WEATHRIN DD.                                                * 00064500
 *********************************************************************/ 00064600
 {                                                                      00064700
   __dyn_t       free_ip;              /* pointer to control block   */ 00064800
                                                                        00064900
   dyninit( &free_ip );                /* Initialize control block   */ 00065000
   free_ip.__ddname = "WEATHRIN";      /* Set DD name of weather ds  */ 00065100
                                                                        00065200
   if( dynfree(&free_ip) != 0 )                                         00065300
     {                                                                  00065400
       sprintf( msgtext,"FREE failed for DDNAME %s. "                   00065500
                        "Error code=%hX, info code=%hX\n",              00065600
                free_ip.__errcode,                                      00065700
                free_ip.__errcode,                                      00065800
                free_ip.__infocode );                                   00065900
       strcpy( sqlstate,"38605" );                                      00066000
     }                                                                  00066100
 } /* end freeWeatherDS */                                              00066200