// BDE - (C) Copyright 1995 by Borland International // transact.c #include "snipit.h" static pCHAR SQLTblName = "SQLTRAN"; // Field descriptor used in creating a table static FLDDesc FldDesc = { // Field 1 - First Name 1, // Field number "NAME", // Field name fldZSTRING, // Field type fldUNKNOWN, // Field subtype 10, // Field size ( 1 or 0, except // BLOb or CHAR field ) 0, // Decimal places ( 0 ) // computed 0, // Offset in record ( 0 ) 0, // Length in bytes ( 0 ) 0, // For Null bits ( 0 ) fldvNOCHECKS, // Validity checks ( 0 ) fldrREADWRITE // Rights }; // Index descriptor - describes the index associated with the table. static IDXDesc IdxDesc = { { "BASEIDX" }, // Name 1, // Number { NULL }, // Tag name (dBASE only) { NULL }, // Optional format FALSE, // Primary? TRUE, // Unique? FALSE, // Descending? TRUE, // Maintained? FALSE, // SubSet? FALSE, // Expression index? NULL, // for QBE only 1, // Fields in key NULL, // Length in bytes FALSE, // Index out of date? 0, // Key type of expression { 1 }, // Array of field numbers { NULL }, // Key expression { NULL }, // Key condition FALSE, // Case insensitive 0, // Block size in bytes 0 // Restructure number }; // Function prototypes static DBIResult CreateAndOpenSQLTable(hDBIDb hDb, phDBICur phTbl, pCHAR pTblName, pCHAR pTblType); static DBIResult AddTranRecord(hDBICur hCur, pCHAR pStr); //===================================================================== // Function: // SQLTran(); // // Description: // This example will describe how to begin a transaction, // verify that the transaction is still active, and commit // (or rollback) the transaction based on its state. // // WARNING: This example requires write access to the SQL server. //===================================================================== void SQLTran (void) { hDBIDb hDb; // Handle to the database. hDBICur hCur; // Handle to the table. hDBIXact hTran; // Handle to the transaction. XInfo TranInfo; // Information about the transaction. pCHAR pTblType; // Buffer to contain the type of the table. DBIResult rslt; // Return value from IDAPI functions eXEnd TranAct; // Transaction action to take: commit or // rollback. UINT16 uLength; // Length of property returned from DbiGetProp Screen("*** SQL Transaction Example ***\r\n"); BREAK_IN_DEBUGGER(); Screen(" Initializing IDAPI..."); if (InitAndConnect2(&hDb) != DBIERR_NONE) { Screen("\r\n*** End of Example ***"); return; } // Get the database type pTblType = (pCHAR)malloc((DBIMAXNAMELEN + 1) * sizeof(CHAR)); if (pTblType == NULL) { Screen(" Error - Out of memory."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); } rslt = DbiGetProp(hDb, dbDATABASETYPE, pTblType, sizeof(DBINAME), &uLength); ChkRslt(rslt, "GetProp"); // Verify that the selected database is a remote SQL server: this // example only works with remote SQL databases such as Interbase // and Oracle. if (!strcmp(pTblType, "STANDARD")) { Screen("This example only works on remote SQL" " databases."); free(pTblType); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Create a sample table and insert records. if (CreateAndOpenSQLTable(hDb, &hCur, SQLTblName, pTblType) != DBIERR_NONE) { free(pTblType); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen("\r\n The table before the transaction..."); rslt = DbiSetToBegin(hCur); ChkRslt(rslt, "SetToBegin"); DisplayTable(hCur, 0); // Start a transaction with a READCOMMIT isolation level rslt = DbiBeginTran(hDb, xilREADCOMMITTED, &hTran); if (ChkRslt(rslt, "BeginTran") == DBIERR_NONE) { // Set the default to commit the transaction. Rollback only if // an error occurs. TranAct = xendCOMMIT; // Verify the state of the transaction rslt = DbiGetTranInfo(hDb, hTran, &TranInfo); ChkRslt(rslt, "GetTranInfo"); if (TranInfo.exState != xsACTIVE) { Screen(" Error - Transaction is not active"); } else { // Transaction is usable. Add some data! Screen("\r\n Inserting two new records..."); rslt = AddTranRecord(hCur, "Angela"); if (rslt != DBIERR_NONE) { // Rollback the transaction if the insert failed TranAct = xendABORT; } rslt = AddTranRecord(hCur, "Bernice"); if (rslt != DBIERR_NONE) { // Rollback the transaction if the insert failed TranAct = xendABORT; } } // End the transaction (committing changes), then reread the // table (updates the cache). Screen(" Ending the transaction..."); rslt = DbiEndTran(hDb, hTran, TranAct); ChkRslt(rslt, "EndTran"); // Note: The call to DbiForceReread is only required in // a multi-user environment when we need to guarantee the // concurrency of data. rslt = DbiForceReread(hCur); ChkRslt(rslt, "ForceReread"); Screen("\r\n The table after the transaction..."); rslt = DbiSetToBegin(hCur); ChkRslt(rslt, "SetToBegin"); DisplayTable(hCur, 0); } rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); // Cleanup. Screen("\r\n Delete the table from the server..."); rslt = DbiDeleteTable(hDb, SQLTblName, pTblType); ChkRslt(rslt, "DeleteTable"); Screen(" Close the database and exit IDAPI..."); CloseDbAndExit(&hDb); free(pTblType); Screen("\r\n*** End of Example ***"); } //===================================================================== // Function: // CreateSQLTable(hDb, phCur, pTblName, pTblType); // // Input: phDb - Pointer to the database handle. // phCur - Cursor to the table. // pTblName - The name of the table to create. // pTblType - The type of table. // // Return: Result returned by IDAPI. // // Description: // This will try to create a table on the SQL server. It will // also insert a few records. // // Note: This example will not work on local tables. //===================================================================== DBIResult CreateAndOpenSQLTable (hDBIDb hDb, phDBICur phCur, pCHAR pTblName, pCHAR pTblType) { DBIResult rslt; // Value returned from IDAPI functions CRTblDesc crTblDsc; // Table descriptor // Initialize the create table descriptor memset(&crTblDsc, 0, sizeof(CRTblDesc)); strcpy(crTblDsc.szTblName, pTblName) ; strcpy(crTblDsc.szTblType, pTblType) ; crTblDsc.iFldCount = 1; crTblDsc.pfldDesc = &FldDesc ; crTblDsc.iIdxCount = 1; crTblDsc.pidxDesc = &IdxDesc ; Screen(" Creating the table..."); rslt = DbiCreateTable(hDb, TRUE, &crTblDsc); if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE) { return rslt; } rslt = DbiOpenTable(hDb, pTblName, pTblType, NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE, NULL, phCur); if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE) { rslt = DbiDeleteTable(hDb, pTblName, pTblType); ChkRslt(rslt, "DeleteTable"); return rslt; } // Add records to the table Screen(" Adding records to the table..."); AddTranRecord(*phCur, "Tom"); AddTranRecord(*phCur, "Jim"); rslt = AddTranRecord(*phCur, "Larry"); // The table handle is returned to the calling function in the phCur // parameter. return rslt; } //===================================================================== // Function: // AddTranRecord(hCur, pStr); // // Input: hCur - The table handle // pStr - The data to insert // // Return: Result of adding the record to the table // // Description: // Insert a record into the table. //===================================================================== DBIResult AddTranRecord (hDBICur hCur, pCHAR pStr) { DBIResult rslt; // Value returned from IDAPI functions. pBYTE pRecBuf; // Record buffer. CURProps TblProps; // Table properties. // Allocate a record buffer. rslt = DbiGetCursorProps(hCur, &TblProps); ChkRslt(rslt, "GetCursorProps"); pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE)); if (pRecBuf == NULL) { Screen(" Error - Out of memory"); return DBIERR_NOMEMORY; } // Clear the record buffer, then add the data. rslt = DbiInitRecord(hCur, pRecBuf); ChkRslt(rslt, "InitRecord"); rslt = DbiPutField(hCur, 1, pRecBuf, (pBYTE) pStr); ChkRslt(rslt, "PutField"); rslt = DbiInsertRecord(hCur, dbiNOLOCK, pRecBuf); ChkRslt(rslt, "InsertRecord"); free(pRecBuf); return rslt; }