home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / interb / InterBase_WI-V6.0-server.exe / server / examples / api / api6.c < prev    next >
C/C++ Source or Header  |  2000-06-23  |  8KB  |  267 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.  * The contents of this file are subject to the Interbase Public
  13.  * License Version 1.0 (the "License"); you may not use this file
  14.  * except in compliance with the License. You may obtain a copy
  15.  * of the License at http://www.Interbase.com/IPL/
  16.  *
  17.  * Software distributed under the License is distributed on an
  18.  * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  19.  * or implied. See the License for the specific language governing
  20.  * rights and limitations under the License.
  21.  *
  22.  * The Original Code was created by Interbase Software Corporation
  23.  * and its successors. Portions created by Borland/Inprise are
  24.  * Copyright (C) 1992-1998 and 1999-2000 Borland/Inprise. Portions
  25.  * created by InterBase Software Corporation are Copyright (C)
  26.  * 1998-1999 InterBase Software Corporation.
  27.  *
  28.  * Copyright (C) 2000 InterBase Software Corporation
  29.  * All Rights Reserved.
  30.  * Contributor(s): ______________________________________.
  31.  */
  32.  
  33.  
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <ibase.h>
  37. #include <stdio.h>
  38. #include "example.h"
  39.  
  40. #define    DEPTLEN        3
  41. #define    PROJLEN        5
  42. #define    BUFLEN        256
  43.  
  44. float increase_factor (double budget);
  45.  
  46. /*
  47.  *  A cursor is declared on this select statement, allowing for
  48.  *  the update of projected_budget field.
  49.  */
  50. char *sel_str =
  51.     "SELECT proj_id, dept_no, projected_budget \
  52.      FROM proj_dept_budget WHERE fiscal_year = 1994 \
  53.      FOR UPDATE OF projected_budget";
  54.  
  55. /* This query is executed prior to the positioned update. */
  56. char *tot_str =
  57.     "SELECT SUM(projected_budget) FROM proj_dept_budget WHERE fiscal_year = 1994";
  58.  
  59.  
  60.  
  61. int main (ARG(int, argc), ARG(char **,argv))
  62. ARGLIST(int argc)
  63. ARGLIST(char **argv)
  64. {
  65.     char                dept_no[DEPTLEN + 2];
  66.     char                proj_id[PROJLEN + 2];
  67.     char                upd_str[BUFLEN];
  68.     double              budget;
  69.     double              tot_budget;
  70.     short               flag0 = 0,
  71.                         flag1 = 0,
  72.                         flag2 = 0,
  73.                         flag3 = 0;
  74.     isc_db_handle       DB = NULL;              /* Database handle */
  75.     isc_tr_handle       trans = NULL;           /* transaction handle */
  76.     long                status[20];             /* status vector */
  77.     char                *cursor = "budget";     /* dynamic cursor name */
  78.     isc_stmt_handle     stmt = NULL;            /* statement handle */
  79.     XSQLDA  ISC_FAR *   osqlda;                 /* output SQLDA */
  80.     XSQLDA  ISC_FAR *   isqlda;                 /* input SQLDA */
  81.     long                fetch_stat;
  82.     char                empdb[128];
  83.  
  84.     if (argc > 1)
  85.         strcpy(empdb, argv[1]);
  86.     else
  87.         strcpy(empdb, "employee.gdb");
  88.  
  89.  
  90.     if (isc_attach_database(status, 0, empdb, &DB, 0, NULL))
  91.     {
  92.         ERREXIT(status, 1)
  93.     }
  94.  
  95.     /*
  96.      *    Prepare and execute the first select statement.
  97.      *    Free the statement handle, when done.
  98.      */
  99.  
  100.     if (isc_dsql_allocate_statement(status, &DB, &stmt))
  101.     {
  102.         ERREXIT(status, 1)
  103.     }
  104.  
  105.     osqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
  106.     osqlda->sqln = 1;
  107.     osqlda->sqld = 1;
  108.     osqlda->version = 1;
  109.  
  110.     if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  111.     {
  112.         ERREXIT(status, 1)
  113.     }
  114.  
  115.     if (isc_dsql_prepare(status, &trans, &stmt, 0, tot_str, 1, osqlda))
  116.         isc_print_status(status);
  117.  
  118.     osqlda->sqlvar[0].sqldata = (char *) &tot_budget;
  119.     osqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  120.     osqlda->sqlvar[0].sqllen  = sizeof(budget);
  121.     osqlda->sqlvar[0].sqlind  = &flag3;
  122.  
  123.     if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  124.     {
  125.         ERREXIT(status, 1)
  126.     }
  127.  
  128.     fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda);
  129.  
  130.     printf("\nTotal budget:  %16.2f\n\n", tot_budget);
  131.  
  132.     if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  133.     {
  134.         ERREXIT(status, 1)
  135.     }
  136.  
  137.     if (isc_commit_transaction(status, &trans))
  138.     {
  139.         ERREXIT(status, 1)
  140.     }
  141.  
  142.     /*
  143.      *    Prepare and execute the positioned update.
  144.      *    Re-use the statement handle as the select cursor.
  145.      */
  146.  
  147.     sprintf(upd_str, "UPDATE proj_dept_budget SET projected_budget = ? \
  148.             WHERE CURRENT OF %s", cursor);
  149.  
  150.     /* Allocate an input SQLDA for the update statement. */
  151.     isqlda = (XSQLDA ISC_FAR *) malloc(XSQLDA_LENGTH(1));
  152.     isqlda->sqln = isqlda->sqld = 1;
  153.     isqlda->version = 1;
  154.  
  155.     isqlda->sqlvar[0].sqldata = (char ISC_FAR *) &budget;
  156.     isqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  157.     isqlda->sqlvar[0].sqllen  = sizeof(budget);
  158.     isqlda->sqlvar[0].sqlind  = &flag3;
  159.                               
  160.     /* Free the output SQLDA, which was used previously. */
  161.     free(osqlda);
  162.  
  163.     /* Re-allocate the output SQLDA. */
  164.     osqlda = (XSQLDA ISC_FAR*) malloc(XSQLDA_LENGTH(3));
  165.     osqlda->sqln = 3;
  166.     osqlda->sqld = 3;
  167.     osqlda->version = 1;
  168.  
  169.     osqlda->sqlvar[0].sqldata = proj_id;
  170.     osqlda->sqlvar[0].sqlind  = &flag0;
  171.  
  172.     osqlda->sqlvar[1].sqldata = dept_no;
  173.     osqlda->sqlvar[1].sqlind  = &flag1;
  174.  
  175.     osqlda->sqlvar[2].sqldata = (char ISC_FAR *) &budget;
  176.     osqlda->sqlvar[2].sqlind  = &flag2;
  177.                               
  178.     if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  179.     {
  180.         ERREXIT(status, 1)
  181.     }
  182.  
  183.     /* Zero the statement handle. */
  184.     stmt = NULL;
  185.  
  186.     if (isc_dsql_allocate_statement(status, &DB, &stmt))
  187.         isc_print_status(status);
  188.     
  189.     if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, 1, osqlda))
  190.         isc_print_status(status);
  191.                
  192.     /* Declare the cursor. */
  193.     isc_dsql_set_cursor_name(status, &stmt, cursor, 0);
  194.  
  195.     if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  196.     {
  197.         ERREXIT(status, 1)
  198.     }
  199.  
  200.     printf("\n%-15s%-10s%-18s%-18s\n\n",
  201.            "PROJ", "DEPT", " CURRENT BUDGET",  "  CHANGED TO");
  202.  
  203.     /*
  204.      *    Fetch and update department budgets.
  205.      */
  206.  
  207.     while ((fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda)) == 0)
  208.     {
  209.         /* Determine the increase percentage. */
  210.         proj_id[PROJLEN] = '\0';
  211.         dept_no[DEPTLEN] = '\0';
  212.         printf("%-15s%-10s%15.2f", proj_id, dept_no, budget);
  213.         budget = budget + budget * increase_factor(budget);
  214.         printf("%15.2f\n", budget);
  215.  
  216.         /* Increase the budget. */
  217.         isc_dsql_exec_immed2(status, &DB, &trans, 0, upd_str, 1, isqlda, NULL);
  218.  
  219.         if (isc_sqlcode(status) == -625)
  220.         {
  221.             printf("\tExceeded budget limit -- not updated.\n");
  222.             continue;
  223.         }
  224.         else
  225.             isc_print_status(status);
  226.     }
  227.  
  228.     if (fetch_stat != 100L)
  229.     {
  230.         ERREXIT(status, 1)
  231.     }
  232.  
  233.     if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  234.     {
  235.         ERREXIT(status, 1)
  236.     }
  237.  
  238.     if (isc_rollback_transaction(status, &trans))
  239.     {
  240.         ERREXIT(status, 1)
  241.     }
  242.  
  243.     if (isc_detach_database(status, &DB))
  244.     {
  245.         ERREXIT(status, 1)
  246.     }
  247.  
  248.     free(osqlda);
  249.     free(isqlda);
  250.  
  251.     return 0;
  252. }
  253.     
  254. /*
  255.  *    Determine a percent increase for the department's budget.
  256.  */
  257. float increase_factor (ARG(double, budget))
  258. ARGLIST(double    budget)
  259. {
  260.     if (budget < 100000L)
  261.         return (float)0.15;
  262.     else if (budget < 500000L)
  263.         return (float)0.10;
  264.     else 
  265.         return (float)0.5;
  266. }
  267.