home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 May / PCWorld_1999-05_cd.bin / software / Vyzkuste / inprise / INTRBASE_55 / EXAMPLES / API / API6.C < prev    next >
C/C++ Source or Header  |  1998-10-18  |  7KB  |  248 lines

  1. /*
  2.  *    Program type:  API Interface
  3.  *
  4.  *    Description:
  5.  *        This program performs a positioned update.
  6.  *        Department budgets are examined and updated using some
  7.  *        percent increase factor, determined at run-time.
  8.  *
  9.  *        The update statement is constructed using a dynamic cursor
  10.  *        name.  The statement handle is freed and re-used by the
  11.  *        update cursor, after being used by another statement.
  12.  */
  13.  
  14.  
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ibase.h>
  18. #include <stdio.h>
  19. #include "example.h"
  20.  
  21. #define    DEPTLEN        3
  22. #define    PROJLEN        5
  23. #define    BUFLEN        256
  24.  
  25. float increase_factor PROTO((double budget));
  26.  
  27. /*
  28.  *  A cursor is declared on this select statement, allowing for
  29.  *  the update of projected_budget field.
  30.  */
  31. char *sel_str =
  32.     "SELECT proj_id, dept_no, projected_budget \
  33.      FROM proj_dept_budget WHERE year = 1994 \
  34.      FOR UPDATE OF projected_budget";
  35.  
  36. /* This query is executed prior to the positioned update. */
  37. char *tot_str =
  38.     "SELECT SUM(projected_budget) FROM proj_dept_budget WHERE year = 1994";
  39.  
  40.  
  41.  
  42. int main (ARG(int, argc), ARG(char **,argv))
  43. ARGLIST(int argc)
  44. ARGLIST(char **argv)
  45. {
  46.     char                dept_no[DEPTLEN + 2];
  47.     char                proj_id[PROJLEN + 2];
  48.     char                upd_str[BUFLEN];
  49.     double              budget;
  50.     double              tot_budget;
  51.     short               flag0 = 0,
  52.                         flag1 = 0,
  53.                         flag2 = 0,
  54.                         flag3 = 0;
  55.     isc_db_handle       DB = NULL;              /* Database handle */
  56.     isc_tr_handle       trans = NULL;           /* transaction handle */
  57.     long                status[20];             /* status vector */
  58.     char                *cursor = "budget";     /* dynamic cursor name */
  59.     isc_stmt_handle     stmt = NULL;            /* statement handle */
  60.     XSQLDA  ISC_FAR *   osqlda;                 /* output SQLDA */
  61.     XSQLDA  ISC_FAR *   isqlda;                 /* input SQLDA */
  62.     long                fetch_stat;
  63.     char                empdb[128];
  64.  
  65.     if (argc > 1)
  66.         strcpy(empdb, argv[1]);
  67.     else
  68.         strcpy(empdb, "employee.gdb");
  69.  
  70.  
  71.     if (isc_attach_database(status, 0, empdb, &DB, 0, NULL))
  72.     {
  73.         ERREXIT(status, 1)
  74.     }
  75.  
  76.     /*
  77.      *    Prepare and execute the first select statement.
  78.      *    Free the statement handle, when done.
  79.      */
  80.  
  81.     if (isc_dsql_allocate_statement(status, &DB, &stmt))
  82.     {
  83.         ERREXIT(status, 1)
  84.     }
  85.  
  86.     osqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
  87.     osqlda->sqln = 1;
  88.     osqlda->sqld = 1;
  89.     osqlda->version = 1;
  90.  
  91.     if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  92.     {
  93.         ERREXIT(status, 1)
  94.     }
  95.  
  96.     if (isc_dsql_prepare(status, &trans, &stmt, 0, tot_str, 1, osqlda))
  97.         isc_print_status(status);
  98.  
  99.     osqlda->sqlvar[0].sqldata = (char *) &tot_budget;
  100.     osqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  101.     osqlda->sqlvar[0].sqllen  = sizeof(budget);
  102.     osqlda->sqlvar[0].sqlind  = &flag3;
  103.  
  104.     if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  105.     {
  106.         ERREXIT(status, 1)
  107.     }
  108.  
  109.     fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda);
  110.  
  111.     printf("\nTotal budget:  %16.2f\n\n", tot_budget);
  112.  
  113.     if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  114.     {
  115.         ERREXIT(status, 1)
  116.     }
  117.  
  118.     if (isc_commit_transaction(status, &trans))
  119.     {
  120.         ERREXIT(status, 1)
  121.     }
  122.  
  123.     /*
  124.      *    Prepare and execute the positioned update.
  125.      *    Re-use the statement handle as the select cursor.
  126.      */
  127.  
  128.     sprintf(upd_str, "UPDATE proj_dept_budget SET projected_budget = ? \
  129.             WHERE CURRENT OF %s", cursor);
  130.  
  131.     /* Allocate an input SQLDA for the update statement. */
  132.     isqlda = (XSQLDA ISC_FAR *) malloc(XSQLDA_LENGTH(1));
  133.     isqlda->sqln = isqlda->sqld = 1;
  134.     isqlda->version = 1;
  135.  
  136.     isqlda->sqlvar[0].sqldata = (char ISC_FAR *) &budget;
  137.     isqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  138.     isqlda->sqlvar[0].sqllen  = sizeof(budget);
  139.     isqlda->sqlvar[0].sqlind  = &flag3;
  140.                               
  141.     /* Free the output SQLDA, which was used previously. */
  142.     free(osqlda);
  143.  
  144.     /* Re-allocate the output SQLDA. */
  145.     osqlda = (XSQLDA ISC_FAR*) malloc(XSQLDA_LENGTH(3));
  146.     osqlda->sqln = 3;
  147.     osqlda->sqld = 3;
  148.     osqlda->version = 1;
  149.  
  150.     osqlda->sqlvar[0].sqldata = proj_id;
  151.     osqlda->sqlvar[0].sqlind  = &flag0;
  152.  
  153.     osqlda->sqlvar[1].sqldata = dept_no;
  154.     osqlda->sqlvar[1].sqlind  = &flag1;
  155.  
  156.     osqlda->sqlvar[2].sqldata = (char ISC_FAR *) &budget;
  157.     osqlda->sqlvar[2].sqlind  = &flag2;
  158.                               
  159.     if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  160.     {
  161.         ERREXIT(status, 1)
  162.     }
  163.  
  164.     /* Zero the statement handle. */
  165.     stmt = NULL;
  166.  
  167.     if (isc_dsql_allocate_statement(status, &DB, &stmt))
  168.         isc_print_status(status);
  169.     
  170.     if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, 1, osqlda))
  171.         isc_print_status(status);
  172.                
  173.     /* Declare the cursor. */
  174.     isc_dsql_set_cursor_name(status, &stmt, cursor, 0);
  175.  
  176.     if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  177.     {
  178.         ERREXIT(status, 1)
  179.     }
  180.  
  181.     printf("\n%-15s%-10s%-18s%-18s\n\n",
  182.            "PROJ", "DEPT", " CURRENT BUDGET",  "  CHANGED TO");
  183.  
  184.     /*
  185.      *    Fetch and update department budgets.
  186.      */
  187.  
  188.     while ((fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda)) == 0)
  189.     {
  190.         /* Determine the increase percentage. */
  191.         proj_id[PROJLEN] = '\0';
  192.         dept_no[DEPTLEN] = '\0';
  193.         printf("%-15s%-10s%15.2f", proj_id, dept_no, budget);
  194.         budget = budget + budget * increase_factor(budget);
  195.         printf("%15.2f\n", budget);
  196.  
  197.         /* Increase the budget. */
  198.         isc_dsql_exec_immed2(status, &DB, &trans, 0, upd_str, 1, isqlda, NULL);
  199.  
  200.         if (isc_sqlcode(status) == -625)
  201.         {
  202.             printf("\tExceeded budget limit -- not updated.\n");
  203.             continue;
  204.         }
  205.         else
  206.             isc_print_status(status);
  207.     }
  208.  
  209.     if (fetch_stat != 100L)
  210.     {
  211.         ERREXIT(status, 1)
  212.     }
  213.  
  214.     if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  215.     {
  216.         ERREXIT(status, 1)
  217.     }
  218.  
  219.     if (isc_rollback_transaction(status, &trans))
  220.     {
  221.         ERREXIT(status, 1)
  222.     }
  223.  
  224.     if (isc_detach_database(status, &DB))
  225.     {
  226.         ERREXIT(status, 1)
  227.     }
  228.  
  229.     free(osqlda);
  230.     free(isqlda);
  231.  
  232.     return 0;
  233. }
  234.     
  235. /*
  236.  *    Determine a percent increase for the department's budget.
  237.  */
  238. float increase_factor (ARG(double, budget))
  239. ARGLIST(double    budget)
  240. {
  241.     if (budget < 100000L)
  242.         return (float)0.15;
  243.     else if (budget < 500000L)
  244.         return (float)0.10;
  245.     else 
  246.         return (float)0.5;
  247. }
  248.