// BDE - (C) Copyright 1995 by Borland International // lsqllive.c #include "snipit.h" static pCHAR szTblName = "SQLLIVE"; // 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 = { { "LIVEIDX" }, // 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: // LiveSQL(); // // Description: // This example shows how to generate a live result set, // so that changes to the query are reflected in the table // on the server. This example allows the user to connect // to any data source which has an alias defined in IDAPI.CFG. // // Note: You need write access to the SQL Server in order to // run this example remotely. Also, the unique index is required // on remote tables for the BDE to have a method of uniquely // identifying a record. //===================================================================== void LiveSQL (void) { DBIResult rslt; // Return value from IDAPI functions hDBIDb hDb; // Handle to the database hDBICur hCur; // Handle to the answer table hDBIStmt hStmt; // Handle to the SQL statement hDBICur hMCur; // Handle to the master table CHAR szQry[100] = { // The text of the SQL statement "SELECT FRSTNAME, LASTNAME \r\n" "FROM SQLLIVE \r\n" }; UINT16 uLength; CURProps TblProps; // Table descriptor CURProps TblMProps; // Table descriptor pBYTE pRecBuf = NULL; // Pointer to the record buffer pBYTE pMRecBuf = 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 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"); // Only use Order By for remote tables only. // Local tables do not allow the use of 'ORDER BY' for // live tables. if (strcmp(szDbType, "STANDARD")) { strcat(szQry, "ORDER BY LASTNAME, FRSTNAME"); } // Create the table if (CreateSQLTable(hDb, szTblName) != DBIERR_NONE) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen(" Perform the following SQL statement on the table:\r\n"); Screen(szQry); Screen("\r\n Prepare the SQL statement..."); rslt = DbiQPrepareExt(hDb, qrylangSQL, szQry, qprepFORUPDATE, &hStmt); if (ChkRslt(rslt, "QPrepareExt") != DBIERR_NONE) { rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen(" Execute the SQL statement..."); rslt = DbiQExec(hStmt, &hCur); if (ChkRslt(rslt, "QExec") != DBIERR_NONE) { 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 = DbiGetCursorProps(hCur, &TblProps); ChkRslt(rslt, "GetCursorProps"); // Check if the answer set is live (exit example if not). if (TblProps.bTempTable == TRUE) { Screen("\r\n Could not get a live answer set..."); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } rslt = DbiOpenTable(hDb, (pCHAR) szTblName, NULL, NULL, NULL, 0, dbiREADONLY, dbiOPENSHARED, xltFIELD, FALSE, NULL, &hMCur); if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE) { rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Get the table properties to allocate memory for the record // buffer. rslt = DbiGetCursorProps(hMCur, &TblMProps); ChkRslt(rslt, "GetCursorProps"); // Allocate memory for the record buffer. pMRecBuf = (pBYTE) malloc(TblMProps.iRecBufSize * sizeof(CHAR)); if (!pMRecBuf) { rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiCloseCursor(&hMCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } rslt = DbiInitRecord(hMCur, pMRecBuf); ChkRslt(rslt, "InitRecord"); Screen("\r\n Display the table using the cursor aqcuired through" " DbiOpenTable:"); DisplayTable(hMCur, 0); // Allocate memory for the record buffer. pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(CHAR)); if (!pRecBuf) { free(pMRecBuf); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiCloseCursor(&hMCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiDeleteTable(hDb, szTblName, NULL); ChkRslt(rslt, "DeleteTable"); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Get the first record in the live query. rslt = DbiSetToBegin(hCur); ChkRslt(rslt, "SetToBegin"); rslt = DbiGetNextRecord(hCur, dbiNOLOCK, pRecBuf, NULL); ChkRslt(rslt, "GetNextRecord"); rslt = DbiGetField(hCur, 1, pRecBuf, szFirst, &bBlank); ChkRslt(rslt, "GetField"); // Modify the First Name of the first record. rslt = DbiPutField(hCur, 1, pRecBuf, szNewFirst); ChkRslt(rslt, "PutField"); Screen("\r\n Modifying the first record in the query result:" "\r\n change the FRSTNAME field from %s to %s....", szFirst, szNewFirst); rslt = DbiModifyRecord(hCur, pRecBuf, TRUE); ChkRslt(rslt, "ModifyRecord"); // Refresh the cursor - only required for remote tables 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 first record reflects the changes made" " to the query)"); DisplayTable(hMCur, 0); Screen("\r\n Close the cursors..."); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); rslt = DbiCloseCursor(&hMCur); ChkRslt(rslt, "CloseCursor"); } else { Screen(" Could not get cursor to the answer table."); } Screen(" Release memory allocated for the query..."); rslt = DbiQFree(&hStmt); ChkRslt(rslt, "QryFree"); // Cleanup Screen(" Delete the table..."); if (!strcmp(szDbType, "STANDARD")) { rslt = DbiDeleteTable(hDb, szTblName, szPARADOX); } else { rslt = DbiDeleteTable(hDb, szTblName, NULL); } ChkRslt(rslt, "DeleteTable"); if (pRecBuf) { free(pRecBuf); } if (pMRecBuf) { free(pMRecBuf); } Screen(" Close the database and exit IDAPI..."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); } //===================================================================== // Function: // CreateSQLTable(hDb, pszTblName, phCur); // // Input: phDb - Pointer to the database handle. // pszTblName - The name of the table to create. // phCur - Handle to the table // // 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 DBINAME szDbType; // Type of the table UINT16 uLength; // Length of the string 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; rslt = DbiGetProp(hDb, dbDATABASETYPE, szDbType, sizeof(DBINAME), &uLength); ChkRslt(rslt, "GetProp"); // Create a Paradox table when working locally if (!strcmp(szDbType, "STANDARD")) { rslt = DbiGetProp(hDb, dbDEFAULTDRIVER, szDbType, sizeof(DBINAME), &uLength); ChkRslt(rslt, "GetProp"); // If no default driver is set if (!strcmp(szDbType, "")) { strcpy(szDbType, szPARADOX); } // Local tables do not require an index, and as indexes are // created differently for local tables, an index is not created. crTblDesc.iIdxCount = 0; crTblDesc.pidxDesc = NULL; // Set the Table Type. strcpy(crTblDesc.szTblType, szDbType); } 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, dbiOPENSHARED, xltFIELD, FALSE, 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, "ClostTable"); 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; }