/***************************************************************************/ /* */ /* (c) Copyright IBM Corp. 2002 All rights reserved. */ /* */ /* This sample program is owned by International Business Machines */ /* Corporation or one of its subsidiaries ("IBM") and is copyrighted */ /* and licensed, not sold. */ /* */ /* You may copy, modify, and distribute this sample program in any */ /* form without payment to IBM, for any purpose including developing, */ /* using, marketing or distributing programs that include or are */ /* derivative works of the sample program. */ /* */ /* The sample program is provided to you on an "AS IS" basis, without */ /* warranty of any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, */ /* EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Some jurisdictions do not allow for the exclusion or limitation of */ /* implied warranties, so the above limitations or exclusions may not */ /* apply to you. IBM shall not be liable for any damages you suffer as */ /* a result of using, modifying or distributing the sample program or */ /* its derivatives. */ /* */ /* Each copy of any portion of this sample program or any derivative */ /* work, must include the above copyright notice and disclaimer of */ /* warranty. */ /* */ /***************************************************************************/ /* The following embedded SQL sample demonstrates using WebSphere MQ as an */ /* XA Resource coordinator with DB2 UDB Version 7.2 and has been tested */ /* using DB2 UDB Version 7.2 FP7 with MQSeries for Windows 2000 V5.2 */ /* service level U200148 (CSD03). */ /* */ /* This sample requires include files from both MQSeries and DB2 UDB */ /* and requires linking utilemb.obj (from DB2 UDB) and linking in both */ /* db2api.lib and mqm.lib. */ /* */ /* Once built, this application executes against the SAMPLE database */ /* and will take any valid SQL statement. */ /* */ /* This sample can be run with the following command: */ /* */ /* mqdb2 SYSTEM.DEFAULT.LOCAL.QUEUE */ /* */ /* For additional information on the necessary configuration changes to */ /* WebSphere MQ, refer to the WebSphere MQ System Administration Guide. */ /* */ /***************************************************************************/ #include #include #include #include /* Header for MQSeries */ #include /* Header for DB2 */ #include /* Header for DB2 */ #include /* Header for DB2 */ #include "utilemb.h" /* Header for DB2 */ #ifdef DB268K /* Need to include ASLM for 68K applications */ #include #endif EXEC SQL INCLUDE SQLCA ; int process_statement( char *); int main(int argc, char **argv) { FILE *fp; /* Declare file and character for sample input */ /* Declare MQI structures needed */ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor for reply */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */ MQBO bo = {MQBO_DEFAULT}; /* begin options */ MQHCONN Hcon; /* connection handle */ MQHOBJ Hobj; /* object handle, server queue */ MQLONG O_options; /* MQOPEN options */ MQLONG C_options; /* MQCLOSE options */ MQLONG OpenCode; /* completion code */ MQLONG CompCode; /* completion code */ MQLONG Reason; /* reason code */ MQLONG CReason; /* reason code (MQCONN) */ MQLONG BackCode; /* Completion code for MQBACK */ MQLONG CmitCode; /* Completion code for MQCMIT */ MQLONG BackReason; /* reason code for MQBACK */ MQLONG CmitReason; /* reason code for MQCMIT */ MQLONG BeginCode; MQLONG BeginReason; MQBYTE buffer[100]; /* message buffer */ MQLONG buflen; /* buffer length */ MQLONG messlen; /* message length received */ char QMName[50]; /* queue manager name */ int rc; printf("Sample mqdb2 start\n"); if (argc < 2) { printf("Missing parameter - logging queue\n"); exit(99); } /******************************************************************/ /* This sample includes an explicit connect (MQCONN), which isn't */ /* required on all MQSeries platforms, because it's intended to */ /* portable. */ /******************************************************************/ QMName[0] = 0; /* default */ if (argc > 2) { strcpy(QMName, argv[2]); } MQCONN(QMName, &Hcon, &CompCode, &CReason); /* report reason and stop if it failed */ if (CompCode == MQCC_FAILED) { printf("MQCONN ended with reason code %ld\n", CReason); exit(CReason); } /******************************************************************/ /* Use first parameter as the name of the logging queue */ /******************************************************************/ strncpy(od.ObjectName, argv[1], (size_t)MQ_Q_NAME_LENGTH); printf("Logging queue is %s\n", od.ObjectName); /******************************************************************/ /* Open the target message queue for output */ /******************************************************************/ O_options = MQOO_OUTPUT /* open queue for output */ + MQOO_FAIL_IF_QUIESCING; /* but not if MQM stopping */ MQOPEN(Hcon, &od, O_options, &Hobj, &OpenCode, &Reason); /**********************************************/ /* report reason, if any; stop if failed */ /**********************************************/ if (Reason != MQRC_NONE) { printf("MQOPEN ended with reason code %ld\n", Reason); } if (OpenCode == MQCC_FAILED) { printf("unable to open queue for output\n"); } CompCode = OpenCode; /* use MQOPEN result for initial test */ fp = stdin; memcpy(md.Format, /* character string format */ MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH); while (CompCode != MQCC_FAILED) { printf("Enter SQL command to process or leave blank to exit program:\n"); if (fgets(buffer, sizeof(buffer), fp) != NULL) { buflen = strlen(buffer); /* length without null */ if (buffer[buflen-1] == '\n') { /* last char is a new-line */ buffer[buflen-1] = '\0'; /* replace new-line with null */ --buflen; /* reduce buffer length */ } } else { buflen = 0; /* treat EOF same as null line */ } /****************************************************************/ /* If we got a buffer, put it to the message queue. */ /****************************************************************/ if (buflen > 0) { MQBEGIN(Hcon, &bo, &BeginCode, &BeginReason); if (BeginCode != MQCC_OK) { printf("MQBEGIN Error Code = %ld, Reason %ld\n", BeginCode, BeginReason); CompCode = MQCC_FAILED; /* get out of the loop */ } else { /********************************/ /* Set appropriate MQMD fields: */ /* Get new MsgId, CorrelId */ /* MQPUT is in syncpoint */ /********************************/ memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId) ); memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId) ); pmo.Options = MQPMO_SYNCPOINT; MQPUT(Hcon, Hobj, &md, &pmo, buflen, buffer, &CompCode, &Reason); /*************************/ /* report reason, if any */ /*************************/ if (Reason != MQRC_NONE) { printf("MQPUT ended with reason code %ld\n", Reason); CompCode = MQCC_FAILED; /* get out of the loop */ } else { /*************************************/ /* Connecting to db2 sample database */ /*************************************/ EXEC SQL CONNECT TO SAMPLE ; EMB_SQL_CHECK( "CONNECT TO SAMPLE" ) ; rc = process_statement( buffer ) ; printf("Enter a C to Commit or R to Rollback changes: "); if (fgets(buffer, sizeof(buffer), fp) != NULL) { buflen = strlen(buffer); /* length without null */ if (buffer[buflen-1] == '\n') { /* last char is a new-line */ buffer[buflen-1] = '\0'; /* replace new-line with null */ --buflen; /* reduce buffer length */ } } if ( (strcmp(buffer, "C") == 0) || (strcmp(buffer, "c") == 0) ) { printf("Changes would be committed...\n"); MQCMIT(Hcon, &CmitCode, &CmitReason); if (CmitReason != MQRC_NONE) { printf("MQCMIT ended with reason code %ld\n", CmitReason); } } else { printf("Changes would be rolled back...\n"); MQBACK(Hcon, &BackCode, &BackReason); if (BackReason != MQRC_NONE) { printf("MQBACK ended with reason code %ld\n", BackReason); } } } /* end MQPUT */ } /* endif MQBEGIN */ } else { /* satisfy end condition when empty line is read */ CompCode = MQCC_FAILED; } } /* end while */ /****************************************************************/ /* Close the target queue (if it was opened) */ /****************************************************************/ if (OpenCode != MQCC_FAILED) { C_options = 0; MQCLOSE(Hcon, &Hobj, C_options, &CompCode, &Reason); if (Reason != MQRC_NONE) { printf("MQCLOSE ended with reason code %ld\n", Reason); } } /****************************************************************/ /* Disconnect from MQM if not already connected */ /****************************************************************/ if (CReason != MQRC_ALREADY_CONNECTED) { MQDISC(&Hcon, &CompCode, &Reason); if (Reason != MQRC_NONE) { printf("MQDISC ended with reason code %ld\n", Reason); } } /******************************************************************/ /* End of mqdb2 */ /******************************************************************/ printf("Sample mqdb2 end\n"); return(0); } /****************************************************************************** * FUNCTION : process_statement * This function processes the inputted statement and then prepares the * procedural SQL implementation to take place. * Taken from adhoc.sqc in samples/c directory ******************************************************************************/ 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 section from ADHOC.SQC */