// BDE - (C) Copyright 1995 by Borland International // updtcrnt.c #include "snipit.h" static pCHAR szTblName = "UPDTCRNT"; // Field Descriptor used in creating a table. static SNIPFAR FLDDesc fldDesc[] = { { // Field 1 - FRSTNAME 1, // Field Number "FRSTNAME", // 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, // Validiy checks ( 0 ) fldrREADWRITE // Rights }, { // Field 2 - LASTNAME 2, "LASTNAME", fldZSTRING, fldUNKNOWN, 12, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE } }; // Index Descriptor - describes the index associated with the table. static IDXDesc IdxDesc = { { "UPDTIDX" }, // 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 2, // Fields in key NULL, // Length in bytes FALSE, // Index out of date? 0, // Key Type of Expression { 2, 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 CreateSQLTable(hDBIDb hDb, pCHAR pszTblName); static DBIResult AddRecord(hDBICur hCur, pCHAR pFirst, pCHAR pLast); static const UINT16 uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]); //===================================================================== // Function: // UpdateCurrent(); // // Description: // This example shows how to set up a cursor on the server for // update. This allows for updating the current record. // // Notes: // // This functionality is only supported by the InterBase 4.0 // server. // // DbiSetToBegin will not modify the current position of the // cursor on the server - the cursor needs to be re-set. // // The 'SQLPASSTHRU MODE' in the InterBase alias used for // this example needs to be set to 'SHARED AUTOCOMMIT' for // this example to work. //===================================================================== void UpdateCurrent (void) { DBIResult rslt; // Return value from IDAPI functions hDBIDb hDb; // Handle to the database hDBICur hCur; // Handle to the result set hDBICur hMCur; // Handle to the table on the server hDBIStmt hStmt; // Handle to the SQL statement hDBIXact hTran = 0; // Transaction Handle CHAR szQuery[100] = { // The text of the SQL statement "SELECT *" " FROM UPDTCRNT" " FOR UPDATE OF FRSTNAME" }; UINT16 uLength; // Length of returned property CURProps TblProps; // Used to determine the size of the // Record buffer. pBYTE pRecBuf = NULL; // Pointer to the record buffer BOOL bBlank; // Determine if the field is blank BYTE szFirst[20]; // Variable to store the current first name BYTE szNewFirst[]="Bob"; // Name to change to CHAR szDbType[DBIMAXNAMELEN]; // Type of the connection CHAR szCursorName[] = "MyCursor"; Screen("*** Live Answer Table Example ***\r\n"); BREAK_IN_DEBUGGER(); Screen(" Initializing IDAPI..."); if (InitAndConnect2(&hDb) != DBIERR_NONE) { Screen("\r\n*** End of Example ***"); return; } rslt = DbiGetProp(hDb, dbDATABASETYPE, szDbType, sizeof(DBINAME), &uLength); ChkRslt(rslt, "GetProp"); // Make certain that the server supports this opperation. if (strcmp(szDbType, "INTRBASE")) { Screen(" Error - 'UPDATE ... WHERE CURRENT OF' is currently" " only supported for InterBase v4.0."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Create the table if (CreateSQLTable(hDb, szTblName) != DBIERR_NONE) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Start a transaction to handle the update to the table rslt = DbiBeginTran(hDb, xilREADCOMMITTED, &hTran); if (ChkRslt(rslt, "BeginTran")) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen(" Perform the following SQL statement on the table:\r\n"); Screen(szQuery); // Prepare the query as a non-live query. Screen("\r\n Prepare the SQL statement..."); rslt = DbiQPrepareExt(hDb, qrylangSQL, szQuery, qprepNONE, &hStmt); if (ChkRslt(rslt, "QPrepareExt") != DBIERR_NONE) { rslt = DbiEndTran(hDb, hTran, xendABORT); ChkRslt(rslt, "EndTran"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen(" Set the name of the cursor..."); rslt = DbiSetProp((hDBIObj)hStmt, stmtCURSORNAME, (UINT32)szCursorName); ChkRslt(rslt, "SetProp"); Screen(" Force the use of a Uni-Directional cursor..."); rslt = DbiSetProp((hDBIObj)hStmt, stmtUNIDIRECTIONAL, TRUE); ChkRslt(rslt, "SetProp"); Screen(" Execute the SQL statement..."); rslt = DbiQExec(hStmt, &hCur); if (ChkRslt(rslt, "QExec") != DBIERR_NONE) { rslt = DbiEndTran(hDb, hTran, xendABORT); ChkRslt(rslt, "EndTran"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Check for a valid cursor. if (hCur) { rslt = DbiOpenTable(hDb, szTblName, NULL, "UPDTIDX", NULL, 0, dbiREADONLY, dbiOPENSHARED, xltFIELD, TRUE, NULL, &hMCur); ChkRslt(rslt, "OpenTable"); Screen(" Display the table using the UPDTIDX index..."); DisplayTable(hMCur, 0); rslt = DbiGetCursorProps(hCur, &TblProps); ChkRslt(rslt, "GetCursorProps"); pRecBuf = (pBYTE)malloc(TblProps.iRecBufSize * sizeof(BYTE)); Screen("\r\n Get the first record in the result set (set the current" " position in the cursor...)"); rslt = DbiGetNextRecord(hCur, dbiNOLOCK, pRecBuf, NULL); ChkRslt(rslt, "GetNextRecord"); rslt = DbiGetField(hCur, 1, pRecBuf, szFirst, &bBlank); ChkRslt(rslt, "GetField"); sprintf(szQuery, "UPDATE UPDTCRNT SET FRSTNAME = '%s' WHERE CURRENT OF" " %s", szNewFirst, szCursorName); Screen("\r\n Modifying a record in the query result:" "\r\n change the FRSTNAME field from %s to %s....", szFirst, szNewFirst); // Can also use DbiQPrepareExt/DbiQExec/DbiQFree rslt = DbiQExecDirect(hDb, qrylangSQL, szQuery, NULL); ChkRslt(rslt, "QExecDirect"); Screen("\r\n Close the cursor..."); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); Screen(" Commit the changes..."); rslt = DbiEndTran(hDb, hTran, xendCOMMIT); ChkRslt(rslt, "EndTran"); // Refresh the cursor Screen("\r\n Resynch the cursor to the table..."); rslt = DbiForceReread(hMCur); ChkRslt(rslt, "ForceReread"); rslt = DbiSetToBegin(hMCur); ChkRslt(rslt, "SetToBegin"); Screen("\r\n Again, display the table opened using DbiOpenTable"); Screen(" (Notice that the table reflects the changes made" " to the query)"); DisplayTable(hMCur, 0); rslt = DbiCloseCursor(&hMCur); ChkRslt(rslt, "CloseCursor"); } else { Screen(" Could not get cursor to the answer set."); } Screen("\r\n Release memory allocated for the query..."); rslt = DbiQFree(&hStmt); ChkRslt(rslt, "QryFree"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); if (pRecBuf) { free(pRecBuf); } Screen(" Close the database and exit IDAPI..."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); } //===================================================================== // Function: // CreateSQLTable(hDb, pszTblName); // // Input: phDb - Pointer to the database handle. // pszTblName - The name of the table to create. // // Return: Result returned by IDAPI. // // Description: // This function will create a table and add records to that // table. //===================================================================== DBIResult CreateSQLTable (hDBIDb hDb, pCHAR pszTblName) { DBIResult rslt; // Value returned from IDAPI functions CRTblDesc crTblDesc; // Table Descriptor hDBICur hCur; // Cursor used for adding records // Initialize the Table Create Descriptor. memset(&crTblDesc, 0, sizeof(CRTblDesc)); strcpy(crTblDesc.szTblName, pszTblName); crTblDesc.iFldCount = uNumFields; crTblDesc.pfldDesc = fldDesc; crTblDesc.iIdxCount = 1; crTblDesc.pidxDesc = &IdxDesc; Screen(" Creating the table..."); rslt = DbiCreateTable(hDb, TRUE, &crTblDesc); if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE) { return rslt; } rslt = DbiOpenTable(hDb, pszTblName, NULL, NULL, NULL, 0, dbiREADWRITE, dbiOPENEXCL, xltFIELD, TRUE, NULL, &hCur); if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE) { rslt = DbiDeleteTable(hDb, pszTblName, NULL); ChkRslt(rslt, "DeleteTable"); return rslt; } // Add records to the table. Screen(" Adding records to the table..."); rslt = AddRecord(hCur, "Tom", "Smith"); rslt = AddRecord(hCur, "Jim", "Jones"); rslt = AddRecord(hCur, "Larry", "Peterson"); rslt = AddRecord(hCur, "Jane", "Jackson"); rslt = AddRecord(hCur, "Mary", "Wong"); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseTable"); return rslt; } //===================================================================== // Function: // AddRecord (hDBICur hCur, pCHAR pFirst, pCHAR pLast) // // Input: hCur - The table handle // pFirst - First Name // pLast - Last Name // // Return: Result of adding the record to the table // // Description: // Insert a record into the table. //===================================================================== DBIResult AddRecord (hDBICur hCur, pCHAR pFirst, pCHAR pLast) { DBIResult rslt; // Return value 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) pFirst); ChkRslt(rslt, "PutField"); rslt = DbiPutField(hCur, 2, pRecBuf, (pBYTE) pLast); ChkRslt(rslt, "PutField"); rslt = DbiInsertRecord(hCur, dbiNOLOCK, pRecBuf); ChkRslt(rslt, "InsertRecord"); free(pRecBuf); return rslt; }