home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / snipit.pak / IDXDBASE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  16.8 KB  |  430 lines

  1. // BDE - (C) Copyright 1995 by Borland International
  2.  
  3. // idxdbase.c
  4. #include "snipit.h"
  5.  
  6. #define NAMELEN  10 // Length of the name field.
  7. #define PLACELEN 20 // Length of the POB field.
  8. #define DATELEN  11 // Display length of a date field: mm\dd\yyyy
  9.  
  10. static const char szTblName[] = "people";
  11. static const char szTblType[] = szDBASE;
  12.  
  13. // Field descriptor used in creating a table.
  14. static SNIPFAR FLDDesc fldDesc[] = {
  15.                           { // Field 1 - First name
  16.                             1,            // Field number
  17.                             "FirstName",  // Field name
  18.                             fldZSTRING,   // Field type
  19.                             fldUNKNOWN,   // Field subtype
  20.                             NAMELEN,      // Field size ( 1 or 0, except
  21.                                           //     BLOB or CHAR field )
  22.                             0,            // Decimal places   ( 0 )
  23.                                           //     computed
  24.                             0,            // Offset in record ( 0 )
  25.                             0,            // Length in bytes  ( 0 )
  26.                             0,            // For NULL bits    ( 0 )
  27.                             fldvNOCHECKS, // Validity checks  ( 0 )
  28.                             fldrREADWRITE // Rights
  29.                           },
  30.                           { // Field 2 - Middle Name
  31.                             2, "MidName", fldZSTRING, fldUNKNOWN,
  32.                             NAMELEN, 0, 0, 0, 0,
  33.                             fldvNOCHECKS, fldrREADWRITE
  34.                           },
  35.                           { // Field 3 - Last Name
  36.                             3, "LName", fldZSTRING, fldUNKNOWN,
  37.                             NAMELEN, 0, 0, 0, 0,
  38.                             fldvNOCHECKS, fldrREADWRITE
  39.                           },
  40.                           { // Field 4 - Date of Birth
  41.                             4, "DOB", fldDATE, fldUNKNOWN,
  42.                             0, 0, 0, 0, 0,
  43.                             fldvNOCHECKS, fldrREADWRITE
  44.                           },
  45.                           { // Field 5 - Place of Birth
  46.                             5, "POB", fldZSTRING, fldUNKNOWN,
  47.                             PLACELEN, 0, 0, 0, 0,
  48.                             fldvNOCHECKS, fldrREADWRITE
  49.                           }
  50.                      };  // Array of field descriptors.
  51.  
  52. // Index descriptor. 
  53. static SNIPFAR IDXDesc idxDesc[] = {
  54.                     {  // Composite Production Index.
  55.                        "",           // Name
  56.                        NULL,         // Number
  57.                        {"FNAME"},    // Tag Name ( for dBASE )
  58.                        { NULL },     // Optional Format ( BTREE,
  59.                                      // HASH, etc )
  60.                        FALSE,        // Primary?
  61.                        FALSE,        // Unique?
  62.                        FALSE,        // Descending?
  63.                        TRUE,         // Maintained?
  64.                        FALSE,        // Subset?
  65.                        TRUE,         // Expression index?
  66.                        NULL,         // For QBE only
  67.                        3,            // Fields in key
  68.                        1,            // Length in bytes
  69.                        FALSE,        // Index out of date?
  70.                        0,            // Key type of expression
  71.                        { 1,2,3 },    // Array of field numbers
  72.                        {"FirstName + MidName + LName" },// Key expression
  73.                        { 0 },        // Key condition
  74.                        FALSE,        // Case insensitive
  75.                        0,            // Block size in bytes
  76.                        0             // Restructure number
  77.                     },
  78.                     {  // Single-field production index.
  79.                        "", NULL, {"LNAME"}, { NULL }, FALSE, FALSE,
  80.                        FALSE, TRUE, FALSE, FALSE, NULL, 1, 1, FALSE,
  81.                        0, { 3 }, { 0 }, { 0 }, FALSE, 0, 0
  82.                     },
  83.                     {  // Single-field production index.
  84.                        "", NULL, {"POB"}, { NULL }, FALSE, FALSE, FALSE,
  85.                        TRUE, FALSE, FALSE, NULL, 1, 1, FALSE, 0, { 5 },
  86.                        { 0 }, { 0 }, FALSE, 0, 0
  87.                     }                                   
  88.                 };
  89.  
  90. static SNIPFAR IDXDesc idxDesc1[] = {
  91.                     {  // Expression index, non-maintained .NDX style index.
  92.                        "FULLNAME.NDX", NULL, { NULL }, { NULL }, FALSE,
  93.                        FALSE, FALSE, FALSE, FALSE, TRUE, NULL, 2, 1,
  94.                        FALSE, 0, { 1,3 }, {"FirstName + LName"}, { 0 },
  95.                        FALSE, 0, 0
  96.                     }
  97.                  };
  98.  
  99. static DBIResult InitTable(phDBIDb phDb);
  100. static DBIResult AddRecord(phDBICur hCur, pCHAR pszFirst, pCHAR pszMiddle,
  101.                            pCHAR pszLast, UINT16 uMonth, UINT16 uDay,
  102.                            UINT16 uYear, pCHAR pszPOB);
  103.  
  104. //=====================================================================
  105. //  Function:
  106. //          IndexDBase();
  107. //
  108. //  Description:
  109. //          This example shows how to set up a dBASE table and dBASE
  110. //          indexes.  This includes expression indexes (multiple field
  111. //          indexes) and the particular needs of the common dBASE index.
  112. //=====================================================================
  113. void
  114. IndexDBase (void)
  115. {
  116.     hDBIDb      hDb;        // Database handle
  117.     hDBICur     hCur;       // Cursor handle
  118.     IDXDesc     *MyDesc;    // Index descriptor
  119.     DBIResult   rslt;       // Return value from IDAPI functions
  120.  
  121.     Screen("*** dBASE Index Example ***\r\n");
  122.  
  123.     BREAK_IN_DEBUGGER();
  124.  
  125.     Screen("    Initializing IDAPI...");
  126.     if (InitAndConnect(&hDb) != DBIERR_NONE)
  127.     {                                        
  128.         Screen("\r\n*** End of Example ***");
  129.         return;
  130.     }
  131.  
  132.     Screen("    Setting the database directory...");
  133.     rslt = DbiSetDirectory(hDb, (pCHAR) szTblDirectory);
  134.     ChkRslt(rslt, "SetDirectory");
  135.  
  136.     // Create the table and add four records.
  137.     if (InitTable(&hDb))
  138.     {
  139.         CloseDbAndExit(&hDb);
  140.         Screen("\r\n*** End of Example ***");
  141.         return;
  142.     }
  143.  
  144.     Screen("    Open the table which we just created in exclusive"
  145.            " mode\r\n        (required in order to add an index to a"
  146.            " dBASE table)...");
  147.     rslt = DbiOpenTable(hDb, (pCHAR) szTblName, (pCHAR) szTblType,
  148.                         NULL, NULL, NULL, dbiREADWRITE, dbiOPENEXCL,
  149.                         xltFIELD, FALSE, NULL, &hCur);
  150.     if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE)
  151.     {
  152.         CloseDbAndExit(&hDb);
  153.         Screen("\r\n*** End of Example ***");
  154.         return;
  155.     }
  156.  
  157.     // Now add the new index to the table.  To add an index, we must have
  158.     //   an exclusive lock on the table which we acquired when opening the
  159.     //   table. Note that the index is automatically opened.
  160.     Screen("    Adding a non-maintained index to the table...");
  161.     rslt = DbiAddIndex(hDb, hCur,(pCHAR) szTblName, (pCHAR) szTblType,
  162.                        idxDesc1, NULL);
  163.     ChkRslt(rslt, "AddIndex");
  164.  
  165.  
  166.     // Close the index. In dBASE, after closing a non-maintained
  167.     //   index will not be kept up-to-date.
  168.     Screen("    Closing the non-maintained index we just added...");
  169.     rslt = DbiCloseIndex(hCur, "FULLNAME.NDX", NULL);
  170.     ChkRslt(rslt, "CloseIndex");
  171.  
  172.     // Now add a record to the table to make the index out-of-date.
  173.     Screen("    Adding a record to invalidate the index...");
  174.     rslt = AddRecord(&hCur, "Charlie", "Joel", "Waternon", 5, 21, 1983,
  175.                      "California");
  176.     ChkRslt(rslt, "AddRecord");
  177.  
  178.     // Open the added index using DbiOpenIndex, which is dBASE-
  179.     // specific.
  180.     Screen("    Open the new index to show that it is out of date...");
  181.  
  182.     rslt = DbiOpenIndex(hCur, "FULLNAME.NDX", NULL);
  183.     ChkRslt(rslt, "OpenIndex");
  184.  
  185.     // Opening the index does not make it the current index.  To make the 
  186.     //   index current we need to switch to it. For a non maintained .NDX
  187.     //   index, we need to supply the index name.
  188.     
  189.     Screen("    Switch to the newly created index that is out of date...");
  190.     rslt = DbiSwitchToIndex(&hCur, "FULLNAME.NDX", NULL, NULL, FALSE);
  191.     ChkRslt(rslt, "SwitchToIndex");
  192.  
  193.     Screen("    Display the table...");
  194.     Screen("\r\n    Note that only 4 entries are displayed even"
  195.            " though there are are 5\r\n        entries in the table"
  196.            " because the index is out of date...");
  197.     DisplayTable(hCur, 0);
  198.  
  199.     // Switch to default order.  We cannot regenerate the index if it
  200.     //   is the currently active index on the cursor.
  201.     Screen("\r\n    Switching to default order...");
  202.  
  203.     rslt = DbiSwitchToIndex(&hCur, NULL, NULL, NULL, FALSE);
  204.     ChkRslt(rslt, "SwitchToIndex");
  205.  
  206.     Screen("\r\n    Regenerating the index...");
  207.     rslt = DbiRegenIndex(hDb, hCur, (pCHAR) szTblName, (pCHAR) szTblType,
  208.                          "FULLNAME.NDX", NULL, NULL);
  209.     ChkRslt(rslt, "RegenIndex");
  210.  
  211.     // Switch back to the non-maintained index. It should now be up-to-date.
  212.     Screen("    Switch to the newly regenerated index...");
  213.     rslt = DbiSwitchToIndex(&hCur, "FULLNAME.NDX", NULL, NULL, FALSE);
  214.     ChkRslt(rslt, "SwitchToIndex");
  215.  
  216.     Screen("    Display the table according to the new index...");
  217.     DisplayTable(hCur, 0);
  218.  
  219.     // Switch to default order.  The default order for a dBASE table is 
  220.     //   the order in which the records were inserted.
  221.     Screen("\r\n    Switching index to show record order...");
  222.  
  223.     rslt = DbiSwitchToIndex(&hCur, NULL, NULL, NULL, FALSE);
  224.     ChkRslt(rslt, "SwitchToIndex");
  225.  
  226.     Screen("    This is the order of the table with no index...");
  227.     DisplayTable(hCur, 0);
  228.  
  229.     MyDesc = (IDXDesc *) malloc(sizeof(IDXDesc));
  230.     if (MyDesc == NULL)
  231.     {
  232.         CloseDbAndExit(&hDb);
  233.         Screen("\r\n*** End of Example ***");
  234.         return;    
  235.     }
  236.  
  237.     // Close the non-maintained index as we are done with this
  238.     //   part of the example.
  239.     Screen("\r\n    Closing the non-maintained index.");
  240.  
  241.     rslt = DbiCloseIndex(hCur, "FULLNAME.NDX", NULL);
  242.     ChkRslt(rslt, "CloseIndex");
  243.  
  244.     // The only indexes that are open now are maintained indexes since we
  245.     //   have already closed the non-maintained index.
  246.  
  247.     // Get any index descriptor (in this case the first one).
  248.     rslt = DbiGetIndexDesc(hCur, 1, MyDesc);
  249.     ChkRslt(rslt, "GetIndexDesc");
  250.  
  251.     Screen("    Switching to an index in the production index... ");
  252.     rslt = DbiSwitchToIndex(&hCur, MyDesc->szName, MyDesc->szTagName, NULL,
  253.                             FALSE);
  254.     ChkRslt(rslt, "SwitchToIndex");
  255.  
  256.     Screen("    This is the order of the table using a tag inside the"
  257.            " production\r\n        index called %s...", MyDesc->szTagName);
  258.     DisplayTable(hCur, 0);
  259.  
  260.     // Delete the table and its related indexes and files from disk.  To
  261.     //   do this we first need to delete the .NDX index and then we close
  262.     //   the table and delete the table.  In this way, IDAPI will delete
  263.     //   the MDX file for us.
  264.  
  265.     Screen("\r\n    Delete the FULLNAME.NDX index. This must be done"
  266.            " separately as it is not\r\n        a part of the"
  267.            " production index...");
  268.     rslt = DbiDeleteIndex(hDb, hCur, (pCHAR) szTblName, (pCHAR) szTblType,
  269.                           "FULLNAME.NDX", NULL, NULL);
  270.     ChkRslt(rslt, "DeleteIndex");
  271.  
  272.     Screen("    Close the %s table...", szTblName);
  273.     rslt = DbiCloseCursor(&hCur);
  274.     ChkRslt(rslt, "CloseCursor");
  275.  
  276.     Screen("    Delete the %s table...", szTblName);
  277.     rslt = DbiDeleteTable(hDb, (pCHAR) szTblName, (pCHAR) szTblType);
  278.     ChkRslt(rslt, "DeleteTable");
  279.  
  280.     free(MyDesc);
  281.  
  282.     Screen("    Close the database and exit IDAPI...");
  283.     CloseDbAndExit(&hDb);
  284.  
  285.     Screen("\r\n*** End of Example ***");
  286. }
  287.  
  288. //=====================================================================
  289. //  Function:
  290. //          InitTable(phDb);
  291. //
  292. //  Input:  phDb    - Pointer to the database handle
  293. //
  294. //  Return: Result of the table initialization
  295. //
  296. //  Description:
  297. //          This function will create a table and fill it
  298. //          with a number of records.  The function uses
  299. //          another function called AddRecord.
  300. //=====================================================================
  301. DBIResult
  302. InitTable (phDBIDb phDb)
  303. {
  304.     DBIResult   rslt;               // Value returned from IDAPI functions
  305.     hDBICur     hCur;               // Cursor handle for the table that is
  306.                                     //   created
  307.     CRTblDesc   crTblDsc;           // Table descriptor
  308.     BOOL        bOverWrite = TRUE;  // Overwrite, yes/no flag
  309.  
  310.     // The number of fields in the table.
  311.     const unsigned uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]);
  312.  
  313.     // Number of indexes to be created when the table is created.
  314.     const unsigned uNumIndexes = sizeof(idxDesc) / sizeof(idxDesc[0]);
  315.  
  316.     // Initialize the table create descriptor.
  317.     memset(&crTblDsc, 0, sizeof(CRTblDesc));
  318.     strcpy(crTblDsc.szTblName, szTblName);
  319.     strcpy(crTblDsc.szTblType, szTblType);
  320.     crTblDsc.iFldCount     = uNumFields;
  321.     crTblDsc.pfldDesc      = fldDesc;
  322.     crTblDsc.iIdxCount     = uNumIndexes;
  323.     crTblDsc.pidxDesc      = idxDesc;    
  324.  
  325.     // Create the table using information supplied in the table
  326.     //   descriptor above.
  327.     Screen("    Creating table and indexes...");
  328.  
  329.     rslt = DbiCreateTable(*phDb, bOverWrite, &crTblDsc);
  330.     if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE)
  331.     {
  332.         return rslt;
  333.     }
  334.  
  335.     rslt = DbiOpenTable(*phDb, (pCHAR) szTblName, (pCHAR) szTblType,
  336.                         NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
  337.                         xltFIELD, FALSE, NULL, &hCur);
  338.     ChkRslt(rslt, "OpenTable");
  339.  
  340.     // Add records to the table.
  341.     Screen("    Adding Records to the table...");
  342.     rslt = AddRecord(&hCur, "Klaus", "John", "Lockwood", 7, 28, 1968,
  343.                      "Chicago");
  344.     rslt = AddRecord(&hCur, "Ann", "Tracy", "Brown", 12, 27, 1969,
  345.                      "Hermosa Beach");
  346.     rslt = AddRecord(&hCur, "John", "Boy", "Krull", 2, 7, 1954,
  347.                      "Ohmaha");
  348.     rslt = AddRecord(&hCur, "Goliath", "Joel", "Raccah", 4, 13, 1970,
  349.                      "Tel Aviv");
  350.  
  351.     // Close the table so it can be reopened from the calling function.
  352.     rslt = DbiCloseCursor(&hCur);
  353.     ChkRslt(rslt, "CloseCursor");
  354.  
  355.     return rslt;
  356. }
  357.  
  358. //=====================================================================
  359. //  Function:
  360. //          AddRecord(phCur, pszFirst, pszMiddle, pszLast, iMonth,
  361. //                    iDay, iYear, pszPOB);
  362. //
  363. //  Input:  phCur       - Pointer to the cursor handle
  364. //          pszFirst    - First name
  365. //          pszMiddle   - Middle name
  366. //          pszLast     - Last name
  367. //          iMonth      - Month of birth
  368. //          iDay        - Day of birth
  369. //          iYear       - Year of birth
  370. //          pszPOB      - Place of birth
  371. //
  372. //  Return: Result of adding the record to the table
  373. //
  374. //  Description:
  375. //          This function will add a record to the given table.
  376. //=====================================================================
  377. DBIResult
  378. AddRecord (phDBICur phCur, pCHAR pszFirst, pCHAR pszMiddle, pCHAR pszLast,
  379.            UINT16 iMonth, UINT16 iDay, UINT16 iYear, pCHAR pszPOB)
  380. {
  381.     DBIDATE     Date;           // Date structure
  382.     DBIResult   rslt;           // Value returned from IDAPI functions
  383.     CURProps    TblProps;       // Table properties
  384.     pBYTE       pRecBuf;        // Record buffer
  385.  
  386.     //  Allocate a record buffer.
  387.     rslt = DbiGetCursorProps(*phCur, &TblProps);
  388.     ChkRslt(rslt, "GetCursorProps");
  389.  
  390.     pRecBuf = (pBYTE) malloc(TblProps.iRecBufSize * sizeof(BYTE));
  391.     if (pRecBuf == NULL)
  392.     {
  393.         return DBIERR_NOMEMORY;
  394.     }
  395.  
  396.     // Make sure we're starting with a clean record buffer.
  397.     rslt = DbiInitRecord(*phCur, pRecBuf);
  398.     ChkRslt(rslt, "InitRecord");
  399.  
  400.     // First Name.
  401.     rslt = DbiPutField(*phCur, 1, pRecBuf, (pBYTE) pszFirst);
  402.     ChkRslt(rslt, "PutField");
  403.  
  404.     // Middle Name.
  405.     rslt = DbiPutField(*phCur, 2, pRecBuf, (pBYTE) pszMiddle);
  406.     ChkRslt(rslt, "PutField");
  407.  
  408.     // Last Name.
  409.     rslt = DbiPutField(*phCur, 3, pRecBuf, (pBYTE) pszLast);
  410.     ChkRslt(rslt, "PutField");
  411.  
  412.     // Date of birth.
  413.     rslt = DbiDateEncode(iMonth, iDay, iYear, &Date);
  414.     ChkRslt(rslt, "DateEncode");
  415.  
  416.     rslt = DbiPutField(*phCur, 4,  pRecBuf, (pBYTE) &Date);
  417.     ChkRslt(rslt, "PutField");
  418.  
  419.     // Place of Birth.
  420.     rslt = DbiPutField(*phCur, 5,  pRecBuf, (pBYTE) pszPOB);
  421.     ChkRslt(rslt, "PutField");
  422.  
  423.     rslt = DbiInsertRecord(*phCur, dbiNOLOCK, pRecBuf),
  424.     ChkRslt(rslt, "InsertRecord");
  425.  
  426.     free(pRecBuf);
  427.  
  428.     return rslt;
  429. }
  430.