/****************************************************************************** ** ** Source File Name = adhoc.sqc ** ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT International Business Machines Corp. 1995, 2000 ** All Rights Reserved. ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ** ** PURPOSE : ** this is an interactive shell for SQL statements, displaying the ** result sets and simple transaction management. ** ** STRUCTURES USED : ** sqlca ** sqlda ** ** APIs USED : ** ** FUNCTIONS DECLARED : ** 'C' COMPILER LIBRARY : ** stdio.h - printf ** string.h - strncpy ** ** OTHER : ** external : [in the file UTIL.C] ** check_error : Checks for SQLCODE error, and prints out any ** related information available. ** init_da: Initialiaze the memory space for an SQLDA. ** alloc_host_vars: Allocate memory to be filled with SQLDA ** data. ** free_da: Frees up memory which has been allocated ** as an SQLDA structure. ** display_col_titles: Display column titles. ** display_da: Display row information. ** ** EXTERNAL DEPENDENCIES : ** - Ensure existence of database for precompile purposes. ** - Precompile with the SQL precompiler (PREP in DB2) ** - Bind to a database (BIND in DB2) ** - Compile and link 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 C, see the: ** - "Programming in C and C++" section of the Application Development Guide ** For more information on Building C Applications, see the: ** - "Building C Applications" section of the Application Building Guide. ** ** For more information on the SQL language see the SQL Reference. ** *******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sqlenv.h> #include <sqlcodes.h> #include <sqlda.h> /* :rk.1:erk. */ #include "utilemb.h" EXEC SQL INCLUDE SQLCA ; /* :rk.2:erk. */ #define SQLSTATE sqlca.sqlstate int process_statement( char * ) ; int main( int argc, char *argv[] ) { int rc ; char sqlInput[256] ; char st[1024] ; EXEC SQL BEGIN DECLARE SECTION ; /* :rk.3:erk. */ char userid[9] ; char passwd[19] ; EXEC SQL END DECLARE SECTION ; printf( "Sample C program : ADHOC interactive SQL\n" ) ; /* Initialize the connection to a database. */ if ( argc == 1 ) { EXEC SQL CONNECT TO sample ; EMB_SQL_CHECK( "CONNECT TO SAMPLE" ) ; } else if ( argc == 3 ) { strcpy( userid, argv[1] ) ; strcpy( passwd, argv[2] ) ; EXEC SQL CONNECT TO sample USER :userid USING :passwd ; /* :rk.4:erk. */ EMB_SQL_CHECK( "CONNECT TO SAMPLE" ) ; /* :rk.5:erk. */ } else { printf( "\nUSAGE: adhoc [userid passwd]\n\n" ) ; return( 1 ) ; } /* endif */ printf( "Connected to database SAMPLE\n" ) ; /* Enter the continuous command line loop. */ *sqlInput = '\0' ; while ( ( *sqlInput != 'q' ) && ( *sqlInput != 'Q' ) ) { /* :rk.6:erk. */ printf( "Enter an SQL statement or 'quit' to Quit :\n" ) ; gets( sqlInput ) ; if ( ( *sqlInput == 'q' ) || ( *sqlInput == 'Q' ) ) break ; if ( *sqlInput == '\0' ) { /* Don't process the statement */ printf( "No characters entered.\n" ) ; continue ; } strcpy( st, sqlInput ) ; while ( sqlInput[strlen( sqlInput ) - 1] == '\\' ) { st[strlen( st ) - 1] = '\0' ; gets( sqlInput ) ; strcat( st, sqlInput ) ; } /* Process the statement. */ rc = process_statement( st ) ; } printf( "Enter 'c' to COMMIT or Any Other key to ROLLBACK the transaction :\n" ) ; gets( sqlInput ) ; if ( ( *sqlInput == 'c' ) || ( *sqlInput == 'C' ) ) { printf( "COMMITING the transactions.\n" ) ; EXEC SQL COMMIT ; /* :rk.7:erk. */ EMB_SQL_CHECK( "COMMIT" ) ; } else { /* assume that the transaction is to be rolled back */ printf( "ROLLING BACK the transactions.\n" ) ; EXEC SQL ROLLBACK ; /* :rk.8:erk. */ EMB_SQL_CHECK( "ROLLBACK" ) ; } EXEC SQL CONNECT RESET ; /* :rk.9:erk. */ EMB_SQL_CHECK( "CONNECT RESET" ) ; return( 0 ) ; } /****************************************************************************** * FUNCTION : process_statement * This function processes the inputted statement and then prepares the * procedural SQL implementation to take place. ******************************************************************************/ int process_statement ( char * sqlInput ) { int counter = 0 ; struct sqlda * sqldaPointer ; short sqlda_d ; EXEC SQL BEGIN DECLARE SECTION ; /* :rk.3:erk. */ char st[1024] ; EXEC SQL END DECLARE SECTION ; strcpy( st, sqlInput ) ; /* :rk.10:erk. */ /* allocate an initial SQLDA temp pointer to obtain information about the inputted "st" */ init_da( &sqldaPointer, 1 ) ; /* :rk.11:erk. */ EXEC SQL PREPARE statement1 from :st ; /* EMB_SQL_CHECK( "PREPARE" ) ; */ EXEC SQL DESCRIBE statement1 INTO :*sqldaPointer ; /* Expecting a return code of 0 or SQL_RC_W236, SQL_RC_W237, SQL_RC_W238, SQL_RC_W239 for cases where this statement is a SELECT statment. */ if ( SQLCODE != 0 && SQLCODE != SQL_RC_W236 && SQLCODE != SQL_RC_W237 && SQLCODE != SQL_RC_W238 && SQLCODE != SQL_RC_W239 ) { /* An unexpected warning/error has occurred. Check the SQLCA. */ EMB_SQL_CHECK( "DESCRIBE" ) ; } /* end if */ sqlda_d = sqldaPointer->sqld ; free( sqldaPointer ) ; if ( sqlda_d > 0 ) { /* :rk.12:erk. */ /* this is a SELECT statement, a number of columns are present in the SQLDA */ if ( SQLCODE == SQL_RC_W236 || SQLCODE == 0) /* this out only needs a SINGLE SQLDA */ init_da( &sqldaPointer, sqlda_d ) ; if ( SQLCODE == SQL_RC_W237 || SQLCODE == SQL_RC_W238 || SQLCODE == SQL_RC_W239 ) /* this output contains columns that need a DOUBLED SQLDA */ init_da( &sqldaPointer, sqlda_d * 2 ) ; /* need to reassign the SQLDA with the correct number of columns to the SQL statement */ EXEC SQL DESCRIBE statement1 INTO :*sqldaPointer ; EMB_SQL_CHECK( "DESCRIBE" ) ; /* allocating the proper amount of memory space needed for the variables */ alloc_host_vars( sqldaPointer ) ; /* :rk.14:erk. */ /* Don't need to check the SQLCODE for declaration of cursors */ EXEC SQL DECLARE pcurs CURSOR FOR statement1 ; /* :rk.15:erk. */ EXEC SQL OPEN pcurs ; /* :rk.15:erk. */ EMB_SQL_CHECK( "OPEN" ) ; EXEC SQL FETCH pcurs USING DESCRIPTOR :*sqldaPointer; /* :rk.16:erk. */ EMB_SQL_CHECK( "FETCH" ) ; /* if the FETCH is successful, obtain data from SQLDA */ /* display the column titles */ display_col_titles( sqldaPointer ) ; /* :rk.17:erk. */ /* display the rows that are fetched */ while ( SQLCODE == 0 ) { counter++ ; display_da( sqldaPointer ) ; /* :rk.18:erk. */ EXEC SQL FETCH pcurs USING DESCRIPTOR :*sqldaPointer ; } /* endwhile */ EXEC SQL CLOSE pcurs ; /* :rk.19:erk. */ EMB_SQL_CHECK( "CLOSE CURSOR" ) ; printf( "\n %d record(s) selected\n\n", counter ) ; /* Free the memory allocated to this SQLDA. */ free_da( sqldaPointer ) ; } else { /* this is not a SELECT statement, execute SQL statement */ /* :rk.13:erk. */ EXEC SQL EXECUTE statement1 ; EMB_SQL_CHECK( "Executing the SQL statement" ) ; } /* end if */ return( 0 ) ; } /* end of program : adhoc.sqc */