/******************************************************************************
**
** Source File Name = mrspsrv2.sqc 1.4
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1995, 1999
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**
** PURPOSE:
** This sample program demonstrates stored procedures
** returning a result set using embedded SQL.
**
** There are two parts to this program:
** - the mrspcli2 executable (placed on the client)
** - the mrspsrv2 library (placed on the server)
**
** Refer to the mrspcli2.sqc program for more details on how
** this program is invoked as the mrspsrv2 routine
** in the mrspsrv library by the EXEC SQL CALL statement.
**
** The mrspsrv2 routine will obtain the median salary of
** employees in the "staff" table of the "sample" database,
** and return all employees with a salary higher than the
** median.
** The median value will be placed in the input/output SQLDA and
** returned to the outcli routine.
**
** EXTERNAL DEPENDENCIES :
** - Existing database for precompile purposes.
** - Precompile with the SQL precompiler (PREP in DB2)
** - Binding to a database (BIND in DB2)
** - Compiling and linking with the IBM Cset++ compiler (AIX and OS/2)
** or the Microsoft Visual C++ compiler (Windows)
** or the compiler supported on your platform.
**
** For more information about these samples see the README file.
**
** For more information on programming in CLI see the:
** - "Building CLI Applications" section of the Application Building Guide, and the
** - CLI Guide and Reference.
**
** For more information on the SQL language see the SQL Reference.
**
*******************************************************************************/
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <sqlenv.h> /* :rk.1:erk. */
#include <sql.h>
#include <sqlda.h>
SQL_API_RC SQL_API_FN mrspsrv2 ( /* :rk.2:erk. */
void *reserved1,
void *reserved2,
struct sqlda *inout_sqlda,
struct sqlca *ca) {
/* Declare a local SQLCA */
EXEC SQL INCLUDE SQLCA;
/* Declare Host Variables */
EXEC SQL BEGIN DECLARE SECTION;
short num_records;
char stmt[512];
EXEC SQL END DECLARE SECTION;
/* Declare local sqlda pointer, and sqlvar variables */
struct sqlda *local_sqlda;
short id;
short ind_id;
char name[10];
short ind_name;
short declen;
double salary;
short ind_salary;
/* Declare Miscellaneous Variables */
int counter = 0;
short precision;
EXEC SQL WHENEVER SQLError GOTO error_exit;
EXEC SQL WHENEVER SQLWARNING CONTINUE;
EXEC SQL DECLARE c1 CURSOR WITH HOLD FOR s1;
/* Alocoate storage for a local sqlda with 3 sqlvars */
local_sqlda = (struct sqlda *) malloc( SQLDASIZE(3) );
/* Setup local_sqlda, (see init_da() in util.c for a generic example */
strncpy(local_sqlda->sqldaid, "SQLDA ", sizeof (local_sqlda->sqldaid));
local_sqlda->sqldabc = (long)SQLDASIZE(3);
local_sqlda->sqln = 3;
local_sqlda->sqld = 3;
local_sqlda->sqlvar[0].sqltype = SQL_TYP_NSMALL;
local_sqlda->sqlvar[0].sqllen = 2;
local_sqlda->sqlvar[0].sqldata = (char *)&id;
local_sqlda->sqlvar[0].sqlind = &ind_id;
local_sqlda->sqlvar[1].sqltype = SQL_TYP_NCHAR;
local_sqlda->sqlvar[1].sqllen = 9;
local_sqlda->sqlvar[1].sqldata = (char *)&name;
local_sqlda->sqlvar[1].sqlind = &ind_name;
local_sqlda->sqlvar[2].sqltype = SQL_TYP_NFLOAT;
local_sqlda->sqlvar[2].sqllen = sizeof(double);
local_sqlda->sqlvar[2].sqldata = (char *) &salary;
local_sqlda->sqlvar[2].sqlind = &ind_salary;
/* Prepare a Statement to Obtain and Order all Salaries */
strcpy( stmt, "SELECT id, name, salary FROM STAFF ORDER BY salary" );
EXEC SQL PREPARE s1 FROM :stmt;
/*Determine the Total Number of Records */
EXEC SQL SELECT COUNT(*) INTO :num_records FROM STAFF; /* :rk.3:erk. */
/* Fetch Salaries until the Median Salary is Obtained */
EXEC SQL OPEN c1;
while ( counter++ < num_records/2 + 1 ) /* :rk.4:erk. */
{
EXEC SQL FETCH c1 USING DESCRIPTOR :*local_sqlda;
}
/* Do NOT close cursor, return remaining result set */
/* EXEC SQL CLOSE c1; */
/* Cursor is delacred WITH Hold, cursor will remain open after COMMIT */
EXEC SQL COMMIT;
/* Precsion for a DECIMAL is 1st byte of short.
Size of a packed decimal is precision/2 + 1;
*/
precision = ((char *)&(local_sqlda->sqlvar[2].sqllen))[0];
/* Copy double from local sqlda to inout sqlda */
memcpy( inout_sqlda->sqlvar[0].sqldata, local_sqlda->sqlvar[2].sqldata,
sizeof(double) );
/* Copy length */
inout_sqlda->sqlvar[0].sqllen = local_sqlda->sqlvar[2].sqllen;
/* Copy Indicator */
if( local_sqlda->sqlvar[2].sqlind != NULL )
{
*inout_sqlda->sqlvar[0].sqlind = *local_sqlda->sqlvar[2].sqlind;
}
/* Return the SQLCA to the Calling Program */ /* :rk.5:erk. */
memcpy( ca, &sqlca, sizeof( struct sqlca ) );
return(SQLZ_DISCONNECT_PROC);
error_exit:
/* An Error has occurred -- ROLLBACK and return to Calling Program */
memcpy( ca, &sqlca, sizeof( struct sqlca ) );
EXEC SQL ROLLBACK;
return(SQLZ_DISCONNECT_PROC);
}