Example: Using the CLI XA transaction connection attributes
This example shows how to use the call level interface (CLI) XA transaction connection attributes.
Note: By using the code examples, you agree to the terms
of the Code license and disclaimer information.
/*************************************************************************
** file = CLIXAEXMP1.c
**
** Example of a typical flow of work in an XA transaction using the CLI.
**
** XA Functions used:
**
** xa_open() -- Open an XA resource for use in a transaction
** xa_prepare() -- Prepare for commitment of work in the transaction
** xa_commit() -- Commit work done in the transaction
**
** CLI Functions used:
**
** SQLAllocHanle SQLBindParameter SQLDisconnect
** SQLError SQLExecute SQLFreeHandle
** SQLPrepare SQLSetConnectAttr SQLSetEnvAttr
**
** This example will:
** - Open the XA transaction manager
** - Open a CLI connection and start a transaction for it using SQL_TXN_CREATE
** - Do some commitable CLI work under this transaction
** - End the transaction on the first connection using SQL_TXN_END
** - Close the first CLI connection and open a second connection
** - Use the SQL_TXN_FIND option to find the previous transaction
** - Do more commitable work on this transaction and end the transaction
** - Use the XA APIs to prepare and commit the work
************************************************************************************/
#define _XA_PROTOTYPES
#define _MULTI_THREADED
#include <xa.h>
#include <stdio.h>
#include <string.h>
#include <sqlcli.h>
#include <time.h>
#include <stdlib.h>
void genXid(XID *xid) {
time_t t;
memset(xid, 0, sizeof(xid));
xid->formatID = 69;
xid->gtrid_length = 4;
xid->bqual_length = 4;
/* xid->data must be a globally unique naming identifier
when taking gtrid and bqual together - the example below
is most likely not unique */
/* gtrid contents */
xid->data[0] = 0xFA;
xid->data[1] = 0xED;
xid->data[2] = 0xFA;
xid->data[3] = 0xED;
time(&t);
/* bqual contents */
xid->data[4] = (((int)t) >> 24) & 0xFF;
xid->data[5] = (((int)t) >> 16) & 0xFF;
xid->data[6] = (((int)t) >> 8) & 0xFF;
xid->data[7] = (((int)t) >> 0) & 0xFF;
}
int main(int argc, char **argv)
{
/***************************************************/
/* Declarations Section */
/***************************************************/
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN rtnc;
SQLINTEGER attr;
SQLINTEGER int_buffer;
SQLINTEGER rlength;
SQLINTEGER buffint;
SQLINTEGER ilen;
SQLCHAR s[80];
SQLCHAR state[10];
SQLCHAR buffer[600];
SQLCHAR sqlstr[600];
SQLINTEGER natErr;
SQLSMALLINT len;
/* Declare local XA variables */
struct TXN_STRUCT new;
XID xid;
char xaOpenFormat[128];
int mainRmid = 1;
int xaRc;
/* Initialize the XA structure variable's (defined in sqlcli.h) */
strcpy(new.tminfo,"MYPRODUCT");
strcpy(new.reserved1,"");
new.timeoutval = 0;
new.locktimeout = 0;
strcpy(new.reserved2,"");
genXid(&xid);
new.XID = &xid;
/* Use the XA APIs to start the transaction manager */
/* The xa_info argument for xa_open MUST include the THDCTL=C keyword
and value when using using CLI with XA transactions */
sprintf(xaOpenFormat, "RDBNAME=*LOCAL THDCTL=C");
xaRc = xa_open(xaOpenFormat, mainRmid, TMNOFLAGS);
printf("xa_open(%s, %d, TMNOFLAGS) = %d\n",
xaOpenFormat, mainRmid, xaRc);
/* Setup the CLI resources */
attr=SQL_TRUE;
rtnc=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
rtnc=SQLSetEnvAttr(henv,SQL_ATTR_SERVER_MODE,&attr,0); /* set server mode */
rtnc=SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
/* Mark the connection as an external transaction and connect */
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_EXTERNAL,&attr,0);
rtnc=SQLConnect(hdbc,NULL,0,NULL,0,NULL,0);
/* Start the transaction */
new.operation = SQL_TXN_CREATE;
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_INFO,&new,0);
/* Do some CLI work */
rtnc=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
strcpy(sqlstr,"insert into tab values(?)");
rtnc=SQLPrepare(hstmt,sqlstr,SQL_NTS);
rtnc=
SQLBindParameter(hstmt,1,1,SQL_INTEGER,SQL_INTEGER,10,2,&buffint,0,&ilen);
buffint=10; /* set the integer value to insert */
rtnc=SQLExecute(hstmt);
if (rtnc!=SQL_SUCCESS)
{
printf("SQLExecute failed with return code: %i \n", rtnc);
rtnc=SQLError(0, 0,hstmt, state, &natErr, buffer, 600, &len);
printf("%i is the SQLCODE\n",natErr);
printf("%i is the length of error text\n",len);
printf("%s is the state\n",state );
printf("%s \n",buffer);
}
else
printf("SQLExecute succeeded, value %i inserted \n", buffint);
/* End the transaction */
new.operation = SQL_TXN_END;
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_INFO,&new,0);
/* Cleanup and disconnect from the first connection */
rtnc=SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
rtnc=SQLDisconnect(hdbc);
/* Mark the second connection as an external transaction and connect */
attr=SQL_TRUE;
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_EXTERNAL,&attr,0);
rtnc=SQLConnect(hdbc,NULL,0,NULL,0,NULL,0);
/* Find the open transaction from the first connection */
new.operation = SQL_TXN_FIND;
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_INFO,&new,0);
/* Do some CLI work on the second connection */
rtnc=SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt);
strcpy(sqlstr,"insert into tab values(?)");
rtnc=SQLPrepare(hstmt,sqlstr,SQL_NTS);
rtnc=
SQLBindParameter(hstmt,1,1,SQL_INTEGER,SQL_INTEGER,10,2,&buffint,0,&ilen);
buffint=15; /* set the integer value to insert */
rtnc=SQLExecute(hstmt);
if (rtnc!=SQL_SUCCESS)
{
printf("SQLExecute failed with return code: %i \n", rtnc);
rtnc=SQLError(0, 0,hstmt, state, &natErr, buffer, 600, &len);
printf("%i is the SQLCODE\n",natErr);
printf("%i is the length of error text\n",len);
printf("%s is the state\n",state );
printf("%s \n",buffer);
}
else
printf("Second SQLExecute succeeded, value %i inserted \n", buffint);
/* End the transaction */
new.operation = SQL_TXN_END;
rtnc=SQLSetConnectAttr(hdbc,SQL_ATTR_TXN_INFO,&new,0);
/* Now, use XA to prepare/commit transaction */
/* Prepare to commit */
xaRc = xa_prepare(&xid, mainRmid, TMNOFLAGS);
printf("xa_prepare(xid, %d, TMNOFLAGS) = %d\n",mainRmid, xaRc);
/* Commit */
if (xaRc != XA_RDONLY) {
xaRc = xa_commit(&xid, mainRmid, TMNOFLAGS);
printf("xa_commit(xid, %d, TMNOFLAGS) = %d\n", mainRmid, xaRc);
}
else {
printf("xa_commit() skipped for read only TX\n");
}
/* Cleanup the CLI resources */
rtnc=SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
rtnc=SQLDisconnect(hdbc);
rtnc=SQLFreeHandle(SQL_HANDLE_DBC,hdbc);
rtnc=SQLFreeHandle(SQL_HANDLE_ENV,henv);
return 0;
}