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

  1. // BDE - (C) Copyright 1995 by Borland International
  2.  
  3. // Sqlbind.C
  4. #include "snipit.h"
  5.  
  6. static pCHAR szTblName = "SQLBIND";
  7.  
  8. // Field Descriptor used in creating a table.
  9. static SNIPFAR FLDDesc fldDesc[] =
  10.                         {
  11.                           { // Field 1 - FRSTNAME
  12.                             1,              // Field Number
  13.                             "FRSTNAME",     // Field Name
  14.                             fldZSTRING,     // Field Type
  15.                             fldUNKNOWN,     // Field Subtype
  16.                             10,             // Field Size ( 1 or 0, except
  17.                                             //     BLOb or CHAR field )
  18.                             0,              // Decimal places ( 0 )
  19.                                             //     computed
  20.                             0,              // Offset in record ( 0 )
  21.                             0,              // Length in Bytes  ( 0 )
  22.                             0,              // For Null Bits    ( 0 )
  23.                             fldvNOCHECKS,   // Validiy checks   ( 0 )
  24.                             fldrREADWRITE   // Rights
  25.                           },
  26.                           { // Field 2 - LASTNAME
  27.                             2, "LASTNAME", fldZSTRING, fldUNKNOWN,
  28.                             10, 0, 0, 0, 0,
  29.                             fldvNOCHECKS, fldrREADWRITE
  30.                           },
  31.                           { // Field 3 - AGE
  32.                             3, "AGE", fldFLOAT, fldUNKNOWN,
  33.                             0, 0, 0, 0, 0,
  34.                             fldvNOCHECKS, fldrREADWRITE
  35.                           }
  36.                        };
  37.  
  38. // Index Descriptor - describes the index associated with the table.
  39. static IDXDesc IdxDesc =
  40.                     {
  41.                         { "BaseIdx" },      // Name
  42.                         1,                  // Number
  43.                         { NULL },           // Tag name (dBASE only)
  44.                         { NULL },           // Optional format
  45.                         FALSE,              // Primary?
  46.                         TRUE,               // Unique?
  47.                         FALSE,              // Descending?
  48.                         TRUE,               // Maintained?
  49.                         FALSE,              // SubSet?
  50.                         FALSE,              // Expression index?
  51.                         NULL,               // for QBE only
  52.                         2,                  // Fields in key
  53.                         NULL,               // Length in bytes
  54.                         FALSE,              // Index out of date?
  55.                         0,                  // Key Type of Expression
  56.                         { 2, 1 },           // Array of field numbers
  57.                         { NULL },           // Key expression
  58.                         { NULL },           // Key Condition
  59.                         FALSE,              // Case insensitive
  60.                         0,                  // Block size in bytes
  61.                         0                   // Restructure number
  62.                     };
  63.  
  64. // Function prototypes
  65. static DBIResult CreateSQLTable(hDBIDb hDb, pCHAR pszTblName, pCHAR pszDbType);
  66. static void CleanUp(pBYTE pRecBuf, pFLDDesc pfldDesc, hDBIStmt *hStmt,
  67.                     hDBIDb *hDb, hDBICur *hCur, hDBICur *hAnsCur,
  68.                     pCHAR szTblName, hDBIXact hTran, CHAR *pszDbType);
  69.  
  70. static const UINT16 uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]);
  71.  
  72. //=====================================================================
  73. //  Function:
  74. //          SQLBind();
  75. //
  76. //  Description:
  77. //          This example shows how to use Parameter Binding with Query's.
  78. //          Parameter binding allows you to re-execute a SQL query with
  79. //          different parameters without having to prepare the query
  80. //          (which is done by calling DbiQPrepareExt) over and over....
  81. //          This can result in dramatic speed improvements.
  82. //
  83. //          This sample shows two examples which search for values in a
  84. //          table:
  85. //            Example 1: The table has been opened.  The table's
  86. //               field description structure and record buffer are
  87. //               used to define the parameter values for DbiQSetParams().
  88. //               This method is useful if the parameters in the SQL
  89. //               query exactly match the field descriptions for the
  90. //               table, as is often found in Inserts and updates. This
  91. //               example inserts records into the table
  92. //
  93. //            Example 2: The table has been opened.  The table's
  94. //               field description structure and record buffer are
  95. //               used to define the parameter values for DbiQSetParams().
  96. //               This method is useful if the parameters in the SQL
  97. //               query exactly match the field descriptions for the
  98. //               table, as is often found in Inserts and updates. This
  99. //               example retreives records matching a certain criterion.
  100. //
  101. //            Example 3: The table has not been opened. The client
  102. //               builds the logical field description structure and record
  103. //               buffer used to define the parameter values for
  104. //               DbiQSetParams().
  105. //
  106. //  WARNING: This example requires write access to the database.
  107. //=====================================================================
  108. void
  109. SQLBind (void)
  110. {
  111.     hDBIDb      hDb = NULL;         // Handle to the Database.
  112.     hDBICur     hCur = NULL;        // Handle to the Table.
  113.     hDBICur     hAnsCur = NULL;     // Handle to the Answer Set
  114.     pCHAR       pszDbType = NULL;   // Type of the Database
  115.     DBIResult   rslt;               // Return value from IDAPI functions
  116.     UINT16      uLength;            // Length of property return from
  117.                                     //   DbiGetProp
  118.     hDBIStmt    hStmt = NULL;       // Handle to the Query Statement
  119.     CURProps    curProps;           // Table Properties
  120.     pBYTE       pRecBuf = NULL;     // Record Buffer
  121.     pFLDDesc    pfldDesc = NULL,    // Field Descriptor for the Table
  122.                 pfldDescT;
  123.     UINT16      uParam, uParams;    // Number of parameters
  124.     UINT16      uRecBufSize;        // Record buffer size
  125.     hDBIXact    hTran = 0;          // Transaction handle
  126.     DFLOAT      age;                // Variable for Age
  127.     int         i;                  // Loop counter
  128.  
  129.     CHAR        szInsert[]     = {    // SQL statement for insert
  130.                  "INSERT INTO SQLBIND (FRSTNAME, LASTNAME, AGE) VALUES"
  131.                  "(?, ?, ?)"
  132.                                };
  133.  
  134.     CHAR        szQry1[]     = {    // SQL statement for Example 1
  135.                  "SELECT * FROM SQLBIND "
  136.                  "WHERE FRSTNAME = ? and LASTNAME = ?"
  137.                                };
  138.  
  139.     CHAR        szQry2[]     = {    // SQL statement for Example 2
  140.                  "SELECT * FROM SQLBIND "
  141.                  "WHERE FRSTNAME = ? or FRSTNAME = ?"
  142.                                };
  143.  
  144.     Screen("*** SQL Parameter Binding Example ***\r\n");
  145.  
  146.     BREAK_IN_DEBUGGER();
  147.  
  148.     Screen("    Initializing IDAPI...");
  149.     if (InitAndConnect2(&hDb) != DBIERR_NONE)
  150.     {
  151.         Screen("\r\n*** End of Example ***");
  152.         return;
  153.     }
  154.  
  155.     pszDbType = (pCHAR)malloc(sizeof(BYTE) * DBIMAXNAMELEN);
  156.     if (!pszDbType)
  157.     {
  158.         Screen("\r\n    Out Of memory!");
  159.         CloseDbAndExit(&hDb);
  160.         Screen("\r\n*** End of Example ***");
  161.         return;
  162.     }
  163.  
  164.     // Set the type of the table - NULL for server database,
  165.     //   database specific value for local tables. Used in
  166.     //   creating and deleting the table.
  167.     rslt = DbiGetProp(hDb, dbDATABASETYPE, pszDbType, sizeof(DBINAME),
  168.                       &uLength);
  169.     ChkRslt(rslt, "GetProp");
  170.  
  171.     if (!strcmp(pszDbType, "STANDARD"))
  172.     {
  173.         rslt = DbiGetProp(hDb, dbDEFAULTDRIVER, pszDbType, sizeof(DBINAME),
  174.                           &uLength);
  175.         ChkRslt(rslt, "GetProp");
  176.  
  177.         if (!strcmp(pszDbType, ""))
  178.         {
  179.             strcpy(pszDbType, szPARADOX);
  180.         }
  181.     }
  182.     else
  183.     {
  184.         free(pszDbType);
  185.         pszDbType = NULL;
  186.     }
  187.     // Create the table
  188.  
  189.     if (CreateSQLTable(hDb, szTblName, pszDbType)
  190.         != DBIERR_NONE)
  191.     {
  192.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  193.                 hTran, pszDbType);
  194.         return;
  195.     }
  196.  
  197.     // Only allow '?' as a parameter marker. Valid only for remote databases.
  198.     if (!pszDbType)
  199.     {
  200.         rslt = DbiSetProp((hDBIObj)hDb, dbPARAMFMTQMARK, TRUE);
  201.         ChkRslt(rslt, "SetProp");
  202.     }
  203.  
  204.     rslt = DbiOpenTable(hDb, szTblName, pszDbType,
  205.                         NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED,
  206.                         xltFIELD, FALSE, NULL, &hCur);
  207.     if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE)
  208.     {
  209.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  210.                 hTran, pszDbType);
  211.         return;
  212.     }
  213.  
  214.     // Set up Record buffer and Field Descriptor.
  215.     rslt = DbiGetCursorProps(hCur, &curProps);
  216.     ChkRslt(rslt, "GetCursorProps");
  217.  
  218.     // Need to use iRecSize as we are directly modifying the record buffer
  219.     uRecBufSize = (UINT16)(curProps.iRecSize * sizeof(BYTE));
  220.  
  221.     pRecBuf = (pBYTE) malloc(uRecBufSize);
  222.     pfldDesc = (pFLDDesc) malloc(curProps.iFields * sizeof(FLDDesc));
  223.     if ((!pfldDesc) || (!pRecBuf))
  224.     {
  225.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  226.                 hTran, pszDbType);
  227.         return;
  228.     }
  229.  
  230.     rslt = DbiGetFieldDescs(hCur, pfldDesc);
  231.     ChkRslt(rslt, "GetFieldDescs");
  232.  
  233.     // Make certain field numbers are not set
  234.     for (i=0; i < curProps.iFields; i++)
  235.     {
  236.         pfldDesc[i].szName[0] = 0;
  237.     }
  238.  
  239.     uParams = curProps.iFields;
  240.  
  241.     ///////////////////////////////////////////////////////////////////////
  242.     // EXAMPLE 1: Table is open. Use field descriptions and
  243.     //            record buffer.
  244.     //
  245.     // INSERT INTO SQLBIND (FRSTNAME, LASTNAME) VALUES (?, ?)
  246.  
  247.     rslt = DbiBeginTran(hDb, xilREADCOMMITTED, &hTran);
  248.     ChkRslt(rslt, "BeginTran");
  249.  
  250.     Screen("\r\n    Prepare the SQL insert statement...");
  251.     rslt = DbiQPrepareExt(hDb, qrylangSQL, szInsert, qprepNONE, &hStmt);
  252.     ChkRslt(rslt, "QPrepareExt");
  253.  
  254.     Screen("    Insert some records using the following SQL statement:\r\n");
  255.     Screen("        %s\r\n", szInsert);
  256.  
  257.     memset((void*)pRecBuf, 0, uRecBufSize);
  258.     memcpy((void*)(pRecBuf + pfldDesc[0].iOffset), "Tracy", 5);
  259.     memcpy((void*)(pRecBuf + pfldDesc[1].iOffset), "Smith", 5);
  260.     age = 24;
  261.     memcpy((void*)(pRecBuf + pfldDesc[2].iOffset), &age, sizeof(age));
  262.  
  263.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  264.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  265.     {
  266.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  267.                 hTran, pszDbType);
  268.         return;
  269.     }
  270.  
  271.     rslt = DbiQExec(hStmt, NULL);
  272.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  273.     {
  274.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  275.                 hTran, pszDbType);
  276.         return;
  277.     }
  278.  
  279.     memset((void*)pRecBuf, 0, uRecBufSize);
  280.     memcpy((void*)(pRecBuf + pfldDesc[0].iOffset), "David", 5);
  281.     memcpy((void*)(pRecBuf + pfldDesc[1].iOffset), "Duncan", 6);
  282.     age = 29;
  283.     memcpy((void*)(pRecBuf + pfldDesc[2].iOffset), &age, sizeof(age));
  284.  
  285.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  286.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  287.     {
  288.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  289.                 hTran, pszDbType);
  290.         return;
  291.     }
  292.  
  293.     rslt = DbiQExec(hStmt, NULL);
  294.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  295.     {
  296.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  297.                 hTran, pszDbType);
  298.         return;
  299.     }
  300.  
  301.     memset((void*)pRecBuf, 0, uRecBufSize);
  302.     memcpy((void*)(pRecBuf + pfldDesc[0].iOffset), "John", 4);
  303.     memcpy((void*)(pRecBuf + pfldDesc[1].iOffset), "Brisco", 6);
  304.     age = 46;
  305.     memcpy((void*)(pRecBuf + pfldDesc[2].iOffset), &age, sizeof(age));
  306.  
  307.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  308.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  309.     {
  310.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  311.                 hTran, pszDbType);
  312.         return;
  313.     }
  314.  
  315.     rslt = DbiQExec(hStmt, NULL);
  316.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  317.     {
  318.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  319.                 hTran, pszDbType);
  320.         return;
  321.     }
  322.  
  323.     rslt = DbiQFree(&hStmt);
  324.     ChkRslt(rslt, "QFree");
  325.  
  326.     rslt = DbiEndTran(hDb, hTran, xendCOMMIT);
  327.     ChkRslt(rslt, "EndTran");
  328.  
  329.     ///////////////////////////////////////////////////////////////////////
  330.     // EXAMPLE 2: Table is open. Use field descriptions and
  331.     //            record buffer.
  332.     //
  333.     // SELECT * FROM SQLBind WHERE FRSTNAME = ? and LASTNAME = ?
  334.  
  335.     uParams = 2;
  336.  
  337.     rslt = DbiBeginTran(hDb, xilREADCOMMITTED, &hTran);
  338.     ChkRslt(rslt, "BeginTran");
  339.  
  340.     Screen("    Perform the following SQL statement on the table:\r\n");
  341.     Screen("        %s", szQry1);
  342.  
  343.     Screen("\r\n    Prepare the SQL statement...");
  344.     rslt = DbiQPrepareExt(hDb, qrylangSQL, szQry1, qprepNONE, &hStmt);
  345.     ChkRslt(rslt, "QPrepare");
  346.  
  347.     Screen("\r\n    Search for Tracy Smith");
  348.  
  349.     memset((void *)pRecBuf, 0, uRecBufSize);
  350.     memcpy((pVOID)(pRecBuf + pfldDesc[0].iOffset), "Tracy", 5);
  351.     memcpy((pVOID)(pRecBuf + pfldDesc[1].iOffset), "Smith", 5);
  352.  
  353.     Screen("    Set the Statement Parameters...");
  354.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  355.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  356.     {
  357.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  358.                 hTran, pszDbType);
  359.         return;
  360.     }
  361.  
  362.     Screen("    Execute the SQL statement...");
  363.     rslt = DbiQExec(hStmt, &hAnsCur);
  364.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  365.     {
  366.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  367.                 hTran, pszDbType);
  368.         return;
  369.     }
  370.  
  371.     // Check for a valid cursor
  372.     if (hAnsCur)
  373.     {
  374.         Screen("    Display the answer table...");
  375.         rslt = DbiSetToBegin(hAnsCur);
  376.         ChkRslt(rslt, "SetToBegin");
  377.  
  378.         DisplayTable(hAnsCur, 0);
  379.  
  380.         Screen("\r\n    Close the cursor to the answer set...");
  381.         rslt = DbiCloseCursor(&hAnsCur);
  382.         ChkRslt(rslt, "CloseCursor");
  383.         hAnsCur = 0;
  384.     }
  385.     else
  386.     {
  387.         Screen("        Could not get cursor to the answer table");
  388.     }
  389.  
  390.     Screen("\r\n    Search for John Brisco");
  391.     Screen("    Note that we do not have to call DbiQPrepareExt...");
  392.  
  393.     memset((void*)pRecBuf, 0, uRecBufSize);
  394.     memcpy((void*)(pRecBuf + pfldDesc[0].iOffset), "John", 4);
  395.     memcpy((void*)(pRecBuf + pfldDesc[1].iOffset), "Brisco", 6);
  396.  
  397.     Screen("    Set the Statement Parameters...");
  398.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  399.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  400.     {
  401.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  402.                 hTran, pszDbType);
  403.         return;
  404.     }
  405.  
  406.     Screen("    Execute the SQL statement...");
  407.     rslt = DbiQExec(hStmt, &hAnsCur);
  408.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  409.     {
  410.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  411.                 hTran, pszDbType);
  412.  
  413.         return;
  414.     }
  415.  
  416.     // Check for a valid cursor
  417.     if (hAnsCur)
  418.     {
  419.         Screen("    Display the answer table...");
  420.         rslt = DbiSetToBegin(hAnsCur);
  421.         ChkRslt(rslt, "SetToBegin");
  422.  
  423.         DisplayTable(hAnsCur, 0);
  424.  
  425.         Screen("\r\n    Close the cursor to the answer set...");
  426.         rslt = DbiCloseCursor(&hAnsCur);
  427.         ChkRslt(rslt, "CloseCursor");
  428.         hAnsCur = 0;
  429.     }
  430.     else
  431.     {
  432.         Screen("        Could not get cursor to the answer table");
  433.     }
  434.     
  435.     Screen("    Release memory allocated for the Query...");
  436.     rslt = DbiQFree(&hStmt);
  437.     ChkRslt(rslt, "QryFree");
  438.  
  439.     if (pRecBuf)
  440.     {
  441.         free(pRecBuf);
  442.         pRecBuf = NULL;
  443.     }
  444.     if (pfldDesc)
  445.     {
  446.         free(pfldDesc);
  447.     }
  448.  
  449.     rslt = DbiEndTran(hDb, hTran, xendCOMMIT);
  450.     ChkRslt(rslt, "EndTran");
  451.  
  452.     Screen("    Close the %s table...", szTblName);
  453.     rslt = DbiCloseCursor(&hCur);
  454.     ChkRslt(rslt, "CloseCursor");
  455.     hCur = 0;
  456.  
  457.     ///////////////////////////////////////////////////////////
  458.     // EXAMPLE 3: Table is not open. Use client-generated
  459.     //            logical field descriptions and record buffer.
  460.     //
  461.     // SELECT * FROM SQLBind WHERE FRSTNAME = ? or FRSTNAME = ?
  462.  
  463.     rslt = DbiBeginTran(hDb, xilREADCOMMITTED, &hTran);
  464.     ChkRslt(rslt, "BeginTran");
  465.  
  466.     uParams = 2;
  467.  
  468.     pfldDesc = (pFLDDesc) malloc(uParams * sizeof(FLDDesc));
  469.     if (pfldDesc == NULL)
  470.     {
  471.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  472.                 hTran, pszDbType);
  473.         return;
  474.     }
  475.  
  476.     memset(pfldDesc, 0, uParams * sizeof(FLDDesc));
  477.  
  478.     // Build the logical field descriptions to pass to DbiQSetParams().
  479.  
  480.     for (pfldDescT = pfldDesc, uParam = 0; uParam < uParams; uParam++, pfldDescT++)
  481.     {
  482.         // The following fields must be set correctly:
  483.         // iFldNum     - field (parameter) number.
  484.         // iFldType    - field type.
  485.         // iUnits1     - required for string fields only.
  486.         // iLen        - for logical types, sizeof (iFldType) or
  487.         //                 iUnits1 + 1 for string types.
  488.         // iOffset     - offset in the record buffer with param value.
  489.  
  490.         pfldDescT->iFldNum     = (UINT16)(uParam + 1);
  491.         pfldDescT->iFldType    = fldZSTRING;  // IDAPI logical type.
  492.         pfldDescT->iUnits1     = 10;          // Units.
  493.         pfldDescT->iLen        = 11;          // Add 1 for NULL term.
  494.         pfldDescT->iOffset     = (UINT16)(uParam
  495.                                      ? pfldDesc[uParam-1].iOffset +
  496.                                        pfldDesc[uParam-1].iLen
  497.                                      : 0);
  498.     }
  499.  
  500.     uRecBufSize = (UINT16)(pfldDesc[uParams-1].iOffset +
  501.                            pfldDesc[uParams-1].iLen);
  502.  
  503.     pRecBuf = (pBYTE) malloc(uRecBufSize * sizeof(BYTE));
  504.     if (!pRecBuf)
  505.     {
  506.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  507.                 hTran, pszDbType);
  508.         return;
  509.     }
  510.  
  511.     memset(pRecBuf, 0, uRecBufSize);
  512.  
  513.     Screen("\r\n    Prepare the SQL statement...");
  514.     rslt = DbiQPrepareExt(hDb, qrylangSQL, szQry2, qprepNONE, &hStmt);
  515.     ChkRslt(rslt, "QPrepare");
  516.  
  517.     Screen("    Perform the following SQL statement on the table:\r\n");
  518.     Screen("        %s", szQry2);
  519.  
  520.     Screen("\r\n    Search for Tracy or David ");
  521.  
  522.     // Place parameter values in IDAPI logical format into the record buffer
  523.  
  524.     Screen("    Set the Statement Parameters...");
  525.     memcpy((pVOID)(pRecBuf + pfldDesc[0].iOffset), "Tracy", 5);
  526.     memcpy((pVOID)(pRecBuf + pfldDesc[1].iOffset), "David", 5);
  527.  
  528.     rslt = DbiQSetParams(hStmt, uParams, pfldDesc, pRecBuf);
  529.     if (ChkRslt(rslt, "QSetParams") != DBIERR_NONE)
  530.     {
  531.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  532.                 hTran, pszDbType);
  533.         return;
  534.     }
  535.  
  536.     Screen("    Execute the SQL statement...");
  537.     rslt = DbiQExec(hStmt, &hAnsCur);
  538.     if (ChkRslt(rslt, "QExec") != DBIERR_NONE)
  539.     {
  540.         CleanUp(pRecBuf, pfldDesc, &hStmt, &hDb, &hCur, &hAnsCur, szTblName,
  541.                 hTran, pszDbType);
  542.         return;
  543.     }
  544.  
  545.     // Check for a valid cursor
  546.     if (hAnsCur)
  547.     {
  548.         Screen("    Display the answer table...");
  549.         rslt = DbiSetToBegin(hAnsCur);
  550.         ChkRslt(rslt, "SetToBegin");
  551.  
  552.         DisplayTable(hAnsCur, 0);
  553.  
  554.         Screen("\r\n    Close the cursor to the answer set...");
  555.         rslt = DbiCloseCursor(&hAnsCur);
  556.         ChkRslt(rslt, "CloseCursor");
  557.         hAnsCur = 0;
  558.     }
  559.     else
  560.     {
  561.         Screen("        Could not get cursor to the answer table");
  562.     }
  563.  
  564.     rslt = DbiQFree(&hStmt);
  565.     ChkRslt(rslt, "QFree");
  566.  
  567.     rslt = DbiEndTran(hDb, hTran, xendCOMMIT);
  568.     ChkRslt(rslt, "EndTran");
  569.      
  570.     // Cleanup
  571.     Screen("    Delete the table...");
  572.     rslt = DbiDeleteTable(hDb, szTblName, pszDbType);
  573.     ChkRslt(rslt, "DeleteTable");
  574.  
  575.     Screen("    Close the Database and exit IDAPI...");
  576.     CloseDbAndExit(&hDb);
  577.  
  578.     if (pRecBuf)
  579.     {
  580.         free(pRecBuf);
  581.     }
  582.  
  583.     if (pfldDesc)
  584.     {
  585.         free(pfldDesc);
  586.     }
  587.  
  588.     if (pszDbType)
  589.     {
  590.         free(pszDbType);
  591.     }
  592.  
  593.     Screen("\r\n*** End of Example ***");
  594. }
  595.  
  596. //=====================================================================
  597. //  Function:
  598. //          CreateSQLTable(hDb, pszTblName, pszDbType);
  599. //
  600. //  Input:  phDb        - Pointer to the database handle.
  601. //          pszTblName  - The name of the table to create.
  602. //          pszDbType   - Type of table to create (Null for Remote tables)
  603. //
  604. //  Return: Result returned by IDAPI.
  605. //
  606. //  Description:
  607. //          This function will create a table on the specified
  608. //          database.
  609. //=====================================================================
  610. DBIResult
  611. CreateSQLTable (hDBIDb hDb, pCHAR pszTblName, pCHAR pszDbType)
  612. {
  613.     DBIResult   rslt;          // Value returned from IDAPI functions
  614.     CRTblDesc   crTblDesc;     // Table Descriptor
  615.  
  616.     // Initialize the Table Create Descriptor.
  617.     memset(&crTblDesc, 0, sizeof(CRTblDesc));
  618.  
  619.     strcpy(crTblDesc.szTblName, pszTblName);
  620.     crTblDesc.iFldCount     = uNumFields;
  621.     crTblDesc.pfldDesc      = fldDesc;
  622.     crTblDesc.iIdxCount     = 1;
  623.     crTblDesc.pidxDesc      = &IdxDesc;
  624.  
  625.     // If a local table
  626.     if (pszDbType)
  627.     {
  628.         // Set the Table Type.
  629.         strcpy(crTblDesc.szTblType, pszDbType);
  630.         // No Indexes
  631.         crTblDesc.iIdxCount     = 0;
  632.         crTblDesc.pidxDesc      = NULL;
  633.         if (!strcmp(pszDbType, szDBASE))
  634.         {
  635.             crTblDesc.pfldDesc[2].iUnits1 = 8;
  636.         }
  637.     }
  638.  
  639.     Screen("    Creating the table...");
  640.     rslt = DbiCreateTable(hDb, TRUE, &crTblDesc);
  641.     if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE)
  642.     {
  643.         return rslt;
  644.     }
  645.  
  646.     return rslt;
  647. }
  648.  
  649. //=====================================================================
  650. //  Function:
  651. //          CleanUp(pRecBuf, pfldDesc, hStmt, hDb, hCur, szTblName, hTran,
  652. //                  szDbName)
  653. //
  654. //  Input:  pRecBuf     - Handle to the Record Buffer
  655. //          pfldDesc    - Field Descriptor
  656. //          hStmt       - Statement object
  657. //          hDb         - Handle to the Database
  658. //          hCur        - The table handle
  659. //          szTblName   - Name of the Table
  660. //          hTran       - Transaction Handle
  661. //          szDbName    - Database Type
  662. //
  663. //  Return: None
  664. //
  665. //  Description:
  666. //          This function is used to free all resources allocated
  667. //          within this example.
  668. //=====================================================================
  669. void CleanUp(pBYTE pRecBuf, pFLDDesc pfldDesc, hDBIStmt *hStmt,
  670.              hDBIDb *hDb, hDBICur *hCur, hDBICur *hAnsCur, pCHAR szTblName,
  671.              hDBIXact hTran, CHAR *pszDbType)
  672.  
  673. {
  674.     DBIResult   rslt;           // Return value from IDAPI
  675.     
  676.     if (*hStmt)
  677.     {
  678.         rslt = DbiQFree(hStmt);
  679.         ChkRslt(rslt, "QryFree");
  680.     }
  681.  
  682.     if (*hCur)
  683.     {
  684.         rslt = DbiCloseCursor(hCur);
  685.         ChkRslt(rslt, "CloseCursor");
  686.     }
  687.  
  688.     if (*hAnsCur)
  689.     {
  690.         rslt = DbiCloseCursor(hAnsCur);
  691.         ChkRslt(rslt, "CloseCursor");
  692.     }
  693.  
  694.     if (hTran)
  695.     {
  696.        rslt = DbiEndTran(*hDb, hTran, xendABORT);
  697.        ChkRslt(rslt, "EndTran");
  698.     }
  699.  
  700.     if (*hDb)
  701.     {
  702.         rslt = DbiDeleteTable(*hDb, szTblName, pszDbType);
  703.         ChkRslt(rslt, "DeleteTable");
  704.         CloseDbAndExit(hDb);
  705.     }
  706.  
  707.     if (pRecBuf)
  708.     {
  709.         free(pRecBuf);
  710.     }
  711.  
  712.     if (pfldDesc)
  713.     {
  714.         free(pfldDesc);
  715.      }
  716.  
  717.     Screen("\r\n*** End of Example ***");
  718.  
  719.     return;
  720. }
  721.