/******************************************************************************* ** ** Source File Name = inpsrv2.c 1.5 ** ** 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 : ** *******************************************************************************/ /******************************************************************** * SAMPLE PROGRAM: inpsrv2.c ********************************************************************/ /*--> SQLL1X43.SCRIPT */ /******************************************************************** * * PURPOSE: This sample program demonstrates stored procedures, * using CLI. It is rewrite of the inpsrv.sqc embedded SQL * stored procedure. * * There are two parts to this program: * - the inpcli2 executable (placed on the client) * - the inpsrv2 library (placed on the server) * CLI stored procedures can be called by either CLI or embbeded * applications. * * The inpsrv function will take the information * received in the SQLDA to create a table and insert the * names of the presidents. * * Refer to the inpcli2.c program for more details on how * this program is invoked as the inpsrv2 function * in the inpsrv2 library by the EXEC SQL CALL statement. * * The SQL CALL statement will pass in 2 identical SQLDA * structures for input and output because all parameters * on the CALL statement are assummed to have both the * input and output attributes. However, only changes * make to the data and indicator fields in the output SQLDA * will be returned to the client program. * * NOTE: One technique to minimize network flow is to set the * variables that returns no output to null on the server program * before returning to the client program. * This can be achieved by setting the value -128 to the * indicator value associated with the data. * * The sqleproc API will call the inpsrv routine stored * in the inpsrv library. * * The inpsrv routine will take the information received * and create a table called "Presidents" in the "sample" * database. It will then place the values it received in * the input SQLDA into the "Presidents" table. * ** 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 <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlda.h> #include <sqlcli1.h> #include "samputil.h" /* Header file for CLI sample code */ int SQL_API_FN inpsrv2( void * reserved1, void * reserved2, struct sqlda * inout_sqlda, struct sqlca * ca ) { /* Declare a local SQLCA */ struct sqlca sqlca ; SQLCHAR table_stmt[80] = "CREATE TABLE " ; SQLCHAR insert_stmt[80] = "INSERT INTO " ; SQLCHAR insert_data[21] ; SQLINTEGER insert_data_ind ; /* Delare Miscellanous Variables */ int cntr ; char * table_name ; short table_name_length ; char * data_item[3] ; short data_item_length[3] ; int num_of_data = 0 ; /* Delare CLI Variables */ SQLHANDLE henv, hdbc, hstmt ; SQLRETURN rc ; /*-----------------------------------------------------------------*/ /* Assign the data from the SQLDA to local variables so that we */ /* don't have to refer to the SQLDA structure further. This will */ /* provide better portability to other platforms such as DB2 MVS */ /* where they receive the parameter list differently. */ /* Note: Strings are not null-terminated in the SQLDA. */ /*-----------------------------------------------------------------*/ table_name = inout_sqlda->sqlvar[0].sqldata ; table_name_length = inout_sqlda->sqlvar[0].sqllen ; num_of_data = inout_sqlda->sqld - 1 ; for ( cntr = 0; cntr < num_of_data; cntr++ ) { data_item[cntr] = inout_sqlda->sqlvar[cntr+1].sqldata ; data_item_length[cntr] = inout_sqlda->sqlvar[cntr+1].sqllen ; } /*-----------------------------------------------------------------*/ /* Setup CLI required environment */ /*-----------------------------------------------------------------*/ SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ; SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc ) ; /*-----------------------------------------------------------------*/ /* Issue NULL Connect, since in CLI we need a statement handle */ /* and thus a connection handle and environment handle. */ /* A connection is not established, rather the current */ /* connection from the calling application is used */ /*-----------------------------------------------------------------*/ SQLConnect( hdbc, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS ) ; SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; /*-----------------------------------------------------------------*/ /* Create President Table */ /* - For simplicity, we'll ignore any errors from the */ /* CREATE TABLE so that you can run this program even when the */ /* table already exists due to a previous run. */ /*-----------------------------------------------------------------*/ strncat( ( char * ) table_stmt, ( char * ) table_name, table_name_length ) ; strcat( ( char * ) table_stmt, " (name CHAR(20))" ) ; SQLExecDirect( hstmt, table_stmt, SQL_NTS ) ; SQLFreeStmt( hstmt, SQL_RESET_PARAMS ) ; /*-----------------------------------------------------------------*/ /* Generate and execute a PREPARE for an INSERT statement, and */ /* then insert the three presidents. */ /*-----------------------------------------------------------------*/ strncat( ( char * ) insert_stmt, ( char * ) table_name, table_name_length ) ; strcat( ( char * ) insert_stmt, " VALUES (?)" ) ; if ( SQLPrepare(hstmt, insert_stmt, SQL_NTS) != SQL_SUCCESS ) goto ext ; /* Bind insert_data to parameter marker */ SQLBindParameter( hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20, 0, insert_data, 21, &insert_data_ind ) ; for ( cntr = 0; cntr < num_of_data; cntr++ ) { strncpy( ( char * ) insert_data, ( char * ) data_item[cntr], data_item_length[cntr]) ; insert_data_ind = data_item_length[cntr] ; if ( SQLExecute( hstmt ) != SQL_SUCCESS ) goto ext ; } /*-----------------------------------------------------------------*/ /* Return to caller */ /* - Copy the SQLCA */ /* - Update the output SQLDA. Since there's no output to */ /* return, we are setting the indicator values to -128 to */ /* return only a null value. */ /* - Commit or Rollback the inserts. */ /*-----------------------------------------------------------------*/ ext: rc = SQLGetSQLCA( henv, hdbc, hstmt, &sqlca ) ; if ( rc != SQL_SUCCESS ) printf( "RC = %d\n", rc ) ; memcpy( ca, &sqlca, sizeof( sqlca ) ) ; if ( inout_sqlda != NULL ) { for ( cntr = 0; cntr < inout_sqlda->sqld; cntr++ ) { if ( inout_sqlda->sqlvar[cntr].sqlind != NULL ) *( inout_sqlda->sqlvar[cntr].sqlind ) = -128 ; } } rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ; rc = SQLEndTran( SQL_HANDLE_DBC, hdbc, SQL_COMMIT ) ; CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ; rc = SQLDisconnect( hdbc ) ; CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ; rc = SQLFreeHandle( SQL_HANDLE_DBC, hdbc ) ; CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ; rc = SQLFreeHandle( SQL_HANDLE_ENV, henv ) ; if ( rc != SQL_SUCCESS ) return( terminate( henv, rc ) ) ; return(1); /* Return SQLZ_DISCONNECT_PROC */ } /*<-- */