// BDE - (C) Copyright 1995 by Borland International // idxdbase.c #include "snipit.h" #define NAMELEN 10 // Length of the name field. #define PLACELEN 20 // Length of the POB field. #define DATELEN 11 // Display length of a date field: mm\dd\yyyy static const char szTblName[] = "people"; static const char szTblType[] = szDBASE; // Field descriptor used in creating a table. static SNIPFAR FLDDesc fldDesc[] = { { // Field 1 - First name 1, // Field number "FirstName", // Field name fldZSTRING, // Field type fldUNKNOWN, // Field subtype NAMELEN, // 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 }, { // Field 2 - Middle Name 2, "MidName", fldZSTRING, fldUNKNOWN, NAMELEN, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { // Field 3 - Last Name 3, "LName", fldZSTRING, fldUNKNOWN, NAMELEN, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { // Field 4 - Date of Birth 4, "DOB", fldDATE, fldUNKNOWN, 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { // Field 5 - Place of Birth 5, "POB", fldZSTRING, fldUNKNOWN, PLACELEN, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE } }; // Array of field descriptors. // Index descriptor. static SNIPFAR IDXDesc idxDesc[] = { { // Composite Production Index. "", // Name NULL, // Number {"FNAME"}, // Tag Name ( for dBASE ) { NULL }, // Optional Format ( BTREE, // HASH, etc ) FALSE, // Primary? FALSE, // Unique? FALSE, // Descending? TRUE, // Maintained? FALSE, // Subset? TRUE, // Expression index? NULL, // For QBE only 3, // Fields in key 1, // Length in bytes FALSE, // Index out of date? 0, // Key type of expression { 1,2,3 }, // Array of field numbers {"FirstName + MidName + LName" },// Key expression { 0 }, // Key condition FALSE, // Case insensitive 0, // Block size in bytes 0 // Restructure number }, { // Single-field production index. "", NULL, {"LNAME"}, { NULL }, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, NULL, 1, 1, FALSE, 0, { 3 }, { 0 }, { 0 }, FALSE, 0, 0 }, { // Single-field production index. "", NULL, {"POB"}, { NULL }, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, NULL, 1, 1, FALSE, 0, { 5 }, { 0 }, { 0 }, FALSE, 0, 0 } }; static SNIPFAR IDXDesc idxDesc1[] = { { // Expression index, non-maintained .NDX style index. "FULLNAME.NDX", NULL, { NULL }, { NULL }, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL, 2, 1, FALSE, 0, { 1,3 }, {"FirstName + LName"}, { 0 }, FALSE, 0, 0 } }; static DBIResult InitTable(phDBIDb phDb); static DBIResult AddRecord(phDBICur hCur, pCHAR pszFirst, pCHAR pszMiddle, pCHAR pszLast, UINT16 uMonth, UINT16 uDay, UINT16 uYear, pCHAR pszPOB); //===================================================================== // Function: // IndexDBase(); // // Description: // This example shows how to set up a dBASE table and dBASE // indexes. This includes expression indexes (multiple field // indexes) and the particular needs of the common dBASE index. //===================================================================== void IndexDBase (void) { hDBIDb hDb; // Database handle hDBICur hCur; // Cursor handle IDXDesc *MyDesc; // Index descriptor DBIResult rslt; // Return value from IDAPI functions Screen("*** dBASE Index Example ***\r\n"); BREAK_IN_DEBUGGER(); Screen(" Initializing IDAPI..."); if (InitAndConnect(&hDb) != DBIERR_NONE) { Screen("\r\n*** End of Example ***"); return; } Screen(" Setting the database directory..."); rslt = DbiSetDirectory(hDb, (pCHAR) szTblDirectory); ChkRslt(rslt, "SetDirectory"); // Create the table and add four records. if (InitTable(&hDb)) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } Screen(" Open the table which we just created in exclusive" " mode\r\n (required in order to add an index to a" " dBASE table)..."); rslt = DbiOpenTable(hDb, (pCHAR) szTblName, (pCHAR) szTblType, NULL, NULL, NULL, dbiREADWRITE, dbiOPENEXCL, xltFIELD, FALSE, NULL, &hCur); if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Now add the new index to the table. To add an index, we must have // an exclusive lock on the table which we acquired when opening the // table. Note that the index is automatically opened. Screen(" Adding a non-maintained index to the table..."); rslt = DbiAddIndex(hDb, hCur,(pCHAR) szTblName, (pCHAR) szTblType, idxDesc1, NULL); ChkRslt(rslt, "AddIndex"); // Close the index. In dBASE, after closing a non-maintained // index will not be kept up-to-date. Screen(" Closing the non-maintained index we just added..."); rslt = DbiCloseIndex(hCur, "FULLNAME.NDX", NULL); ChkRslt(rslt, "CloseIndex"); // Now add a record to the table to make the index out-of-date. Screen(" Adding a record to invalidate the index..."); rslt = AddRecord(&hCur, "Charlie", "Joel", "Waternon", 5, 21, 1983, "California"); ChkRslt(rslt, "AddRecord"); // Open the added index using DbiOpenIndex, which is dBASE- // specific. Screen(" Open the new index to show that it is out of date..."); rslt = DbiOpenIndex(hCur, "FULLNAME.NDX", NULL); ChkRslt(rslt, "OpenIndex"); // Opening the index does not make it the current index. To make the // index current we need to switch to it. For a non maintained .NDX // index, we need to supply the index name. Screen(" Switch to the newly created index that is out of date..."); rslt = DbiSwitchToIndex(&hCur, "FULLNAME.NDX", NULL, NULL, FALSE); ChkRslt(rslt, "SwitchToIndex"); Screen(" Display the table..."); Screen("\r\n Note that only 4 entries are displayed even" " though there are are 5\r\n entries in the table" " because the index is out of date..."); DisplayTable(hCur, 0); // Switch to default order. We cannot regenerate the index if it // is the currently active index on the cursor. Screen("\r\n Switching to default order..."); rslt = DbiSwitchToIndex(&hCur, NULL, NULL, NULL, FALSE); ChkRslt(rslt, "SwitchToIndex"); Screen("\r\n Regenerating the index..."); rslt = DbiRegenIndex(hDb, hCur, (pCHAR) szTblName, (pCHAR) szTblType, "FULLNAME.NDX", NULL, NULL); ChkRslt(rslt, "RegenIndex"); // Switch back to the non-maintained index. It should now be up-to-date. Screen(" Switch to the newly regenerated index..."); rslt = DbiSwitchToIndex(&hCur, "FULLNAME.NDX", NULL, NULL, FALSE); ChkRslt(rslt, "SwitchToIndex"); Screen(" Display the table according to the new index..."); DisplayTable(hCur, 0); // Switch to default order. The default order for a dBASE table is // the order in which the records were inserted. Screen("\r\n Switching index to show record order..."); rslt = DbiSwitchToIndex(&hCur, NULL, NULL, NULL, FALSE); ChkRslt(rslt, "SwitchToIndex"); Screen(" This is the order of the table with no index..."); DisplayTable(hCur, 0); MyDesc = (IDXDesc *) malloc(sizeof(IDXDesc)); if (MyDesc == NULL) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Close the non-maintained index as we are done with this // part of the example. Screen("\r\n Closing the non-maintained index."); rslt = DbiCloseIndex(hCur, "FULLNAME.NDX", NULL); ChkRslt(rslt, "CloseIndex"); // The only indexes that are open now are maintained indexes since we // have already closed the non-maintained index. // Get any index descriptor (in this case the first one). rslt = DbiGetIndexDesc(hCur, 1, MyDesc); ChkRslt(rslt, "GetIndexDesc"); Screen(" Switching to an index in the production index... "); rslt = DbiSwitchToIndex(&hCur, MyDesc->szName, MyDesc->szTagName, NULL, FALSE); ChkRslt(rslt, "SwitchToIndex"); Screen(" This is the order of the table using a tag inside the" " production\r\n index called %s...", MyDesc->szTagName); DisplayTable(hCur, 0); // Delete the table and its related indexes and files from disk. To // do this we first need to delete the .NDX index and then we close // the table and delete the table. In this way, IDAPI will delete // the MDX file for us. Screen("\r\n Delete the FULLNAME.NDX index. This must be done" " separately as it is not\r\n a part of the" " production index..."); rslt = DbiDeleteIndex(hDb, hCur, (pCHAR) szTblName, (pCHAR) szTblType, "FULLNAME.NDX", NULL, NULL); ChkRslt(rslt, "DeleteIndex"); Screen(" Close the %s table...", szTblName); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); Screen(" Delete the %s table...", szTblName); rslt = DbiDeleteTable(hDb, (pCHAR) szTblName, (pCHAR) szTblType); ChkRslt(rslt, "DeleteTable"); free(MyDesc); Screen(" Close the database and exit IDAPI..."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); } //===================================================================== // Function: // InitTable(phDb); // // Input: phDb - Pointer to the database handle // // Return: Result of the table initialization // // Description: // This function will create a table and fill it // with a number of records. The function uses // another function called AddRecord. //===================================================================== DBIResult InitTable (phDBIDb phDb) { DBIResult rslt; // Value returned from IDAPI functions hDBICur hCur; // Cursor handle for the table that is // created CRTblDesc crTblDsc; // Table descriptor BOOL bOverWrite = TRUE; // Overwrite, yes/no flag // The number of fields in the table. const unsigned uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]); // Number of indexes to be created when the table is created. const unsigned uNumIndexes = sizeof(idxDesc) / sizeof(idxDesc[0]); // Initialize the table create descriptor. memset(&crTblDsc, 0, sizeof(CRTblDesc)); strcpy(crTblDsc.szTblName, szTblName); strcpy(crTblDsc.szTblType, szTblType); crTblDsc.iFldCount = uNumFields; crTblDsc.pfldDesc = fldDesc; crTblDsc.iIdxCount = uNumIndexes; crTblDsc.pidxDesc = idxDesc; // Create the table using information supplied in the table // descriptor above. Screen(" Creating table and indexes..."); rslt = DbiCreateTable(*phDb, bOverWrite, &crTblDsc); if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE) { return rslt; } rslt = DbiOpenTable(*phDb, (pCHAR) szTblName, (pCHAR) szTblType, NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE, NULL, &hCur); ChkRslt(rslt, "OpenTable"); // Add records to the table. Screen(" Adding Records to the table..."); rslt = AddRecord(&hCur, "Klaus", "John", "Lockwood", 7, 28, 1968, "Chicago"); rslt = AddRecord(&hCur, "Ann", "Tracy", "Brown", 12, 27, 1969, "Hermosa Beach"); rslt = AddRecord(&hCur, "John", "Boy", "Krull", 2, 7, 1954, "Ohmaha"); rslt = AddRecord(&hCur, "Goliath", "Joel", "Raccah", 4, 13, 1970, "Tel Aviv"); // Close the table so it can be reopened from the calling function. rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); return rslt; } //===================================================================== // Function: // AddRecord(phCur, pszFirst, pszMiddle, pszLast, iMonth, // iDay, iYear, pszPOB); // // Input: phCur - Pointer to the cursor handle // pszFirst - First name // pszMiddle - Middle name // pszLast - Last name // iMonth - Month of birth // iDay - Day of birth // iYear - Year of birth // pszPOB - Place of birth // // Return: Result of adding the record to the table // // Description: // This function will add a record to the given table. //===================================================================== DBIResult AddRecord (phDBICur phCur, pCHAR pszFirst, pCHAR pszMiddle, pCHAR pszLast, UINT16 iMonth, UINT16 iDay, UINT16 iYear, pCHAR pszPOB) { DBIDATE Date; // Date structure DBIResult rslt; // Value returned from IDAPI functions CURProps TblProps; // Table properties pBYTE pRecBuf; // Record buffer // Allocate a record buffer. rslt = DbiGetCursorProps(*phCur, &TblProps); ChkRslt(rslt, "GetCursorProps"); pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE)); if (pRecBuf == NULL) { return DBIERR_NOMEMORY; } // Make sure we're starting with a clean record buffer. rslt = DbiInitRecord(*phCur, pRecBuf); ChkRslt(rslt, "InitRecord"); // First Name. rslt = DbiPutField(*phCur, 1, pRecBuf, (pBYTE) pszFirst); ChkRslt(rslt, "PutField"); // Middle Name. rslt = DbiPutField(*phCur, 2, pRecBuf, (pBYTE) pszMiddle); ChkRslt(rslt, "PutField"); // Last Name. rslt = DbiPutField(*phCur, 3, pRecBuf, (pBYTE) pszLast); ChkRslt(rslt, "PutField"); // Date of birth. rslt = DbiDateEncode(iMonth, iDay, iYear, &Date); ChkRslt(rslt, "DateEncode"); rslt = DbiPutField(*phCur, 4, pRecBuf, (pBYTE) &Date); ChkRslt(rslt, "PutField"); // Place of Birth. rslt = DbiPutField(*phCur, 5, pRecBuf, (pBYTE) pszPOB); ChkRslt(rslt, "PutField"); rslt = DbiInsertRecord(*phCur, dbiNOLOCK, pRecBuf), ChkRslt(rslt, "InsertRecord"); free(pRecBuf); return rslt; }