api6.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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.Inprise.com/IPL.html
  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 Inprise Corporation
  23. * and its predecessors. Portions created by Inprise Corporation are
  24. * Copyright (C) Inprise Corporation.
  25. *
  26. * All Rights Reserved.
  27. * Contributor(s): ______________________________________.
  28. */
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <ibase.h>
  32. #include <stdio.h>
  33. #include "example.h"
  34. #define DEPTLEN 3
  35. #define PROJLEN 5
  36. #define BUFLEN 256
  37. float increase_factor (double budget);
  38. /*
  39. * A cursor is declared on this select statement, allowing for
  40. * the update of projected_budget field.
  41. */
  42. char *sel_str =
  43. "SELECT proj_id, dept_no, projected_budget \
  44. FROM proj_dept_budget WHERE fiscal_year = 1994 \
  45. FOR UPDATE OF projected_budget";
  46. /* This query is executed prior to the positioned update. */
  47. char *tot_str =
  48. "SELECT SUM(projected_budget) FROM proj_dept_budget WHERE fiscal_year = 1994";
  49. int main (int argc, char** argv)
  50. {
  51. char dept_no[DEPTLEN + 2];
  52. char proj_id[PROJLEN + 2];
  53. char upd_str[BUFLEN];
  54. double budget;
  55. double tot_budget;
  56. short flag0 = 0,
  57. flag1 = 0,
  58. flag2 = 0,
  59. flag3 = 0;
  60. isc_db_handle DB = NULL; /* Database handle */
  61. isc_tr_handle trans = NULL; /* transaction handle */
  62. ISC_STATUS_ARRAY status; /* status vector */
  63. char *cursor = "budget"; /* dynamic cursor name */
  64. isc_stmt_handle stmt = NULL; /* statement handle */
  65. XSQLDA * osqlda; /* output SQLDA */
  66. XSQLDA * isqlda; /* input SQLDA */
  67. long fetch_stat;
  68. char empdb[128];
  69. if (argc > 1)
  70. strcpy(empdb, argv[1]);
  71. else
  72. strcpy(empdb, "employee.fdb");
  73. if (isc_attach_database(status, 0, empdb, &DB, 0, NULL))
  74. {
  75. ERREXIT(status, 1)
  76. }
  77. /*
  78. * Prepare and execute the first select statement.
  79. * Free the statement handle, when done.
  80. */
  81. if (isc_dsql_allocate_statement(status, &DB, &stmt))
  82. {
  83. ERREXIT(status, 1)
  84. }
  85. osqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
  86. osqlda->sqln = 1;
  87. osqlda->sqld = 1;
  88. osqlda->version = 1;
  89. if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  90. {
  91. ERREXIT(status, 1)
  92. }
  93. if (isc_dsql_prepare(status, &trans, &stmt, 0, tot_str, 1, osqlda))
  94. isc_print_status(status);
  95. osqlda->sqlvar[0].sqldata = (char *) &tot_budget;
  96. osqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  97. osqlda->sqlvar[0].sqllen = sizeof(budget);
  98. osqlda->sqlvar[0].sqlind = &flag3;
  99. if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  100. {
  101. ERREXIT(status, 1)
  102. }
  103. fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda);
  104. printf("\nTotal budget: %16.2f\n\n", tot_budget);
  105. if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  106. {
  107. ERREXIT(status, 1)
  108. }
  109. if (isc_commit_transaction(status, &trans))
  110. {
  111. ERREXIT(status, 1)
  112. }
  113. /*
  114. * Prepare and execute the positioned update.
  115. * Re-use the statement handle as the select cursor.
  116. */
  117. sprintf(upd_str, "UPDATE proj_dept_budget SET projected_budget = ? \
  118. WHERE CURRENT OF %s", cursor);
  119. /* Allocate an input SQLDA for the update statement. */
  120. isqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
  121. isqlda->sqln = isqlda->sqld = 1;
  122. isqlda->version = 1;
  123. isqlda->sqlvar[0].sqldata = (char *) &budget;
  124. isqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
  125. isqlda->sqlvar[0].sqllen = sizeof(budget);
  126. isqlda->sqlvar[0].sqlind = &flag3;
  127. /* Free the output SQLDA, which was used previously. */
  128. free(osqlda);
  129. /* Re-allocate the output SQLDA. */
  130. osqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(3));
  131. osqlda->sqln = 3;
  132. osqlda->sqld = 3;
  133. osqlda->version = 1;
  134. osqlda->sqlvar[0].sqldata = proj_id;
  135. osqlda->sqlvar[0].sqlind = &flag0;
  136. osqlda->sqlvar[1].sqldata = dept_no;
  137. osqlda->sqlvar[1].sqlind = &flag1;
  138. osqlda->sqlvar[2].sqldata = (char *) &budget;
  139. osqlda->sqlvar[2].sqlind = &flag2;
  140. if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
  141. {
  142. ERREXIT(status, 1)
  143. }
  144. /* Zero the statement handle. */
  145. stmt = NULL;
  146. if (isc_dsql_allocate_statement(status, &DB, &stmt))
  147. isc_print_status(status);
  148. if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, 1, osqlda))
  149. isc_print_status(status);
  150. /* Declare the cursor. */
  151. isc_dsql_set_cursor_name(status, &stmt, cursor, 0);
  152. if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  153. {
  154. ERREXIT(status, 1)
  155. }
  156. printf("\n%-15s%-10s%-18s%-18s\n\n",
  157. "PROJ", "DEPT", " CURRENT BUDGET", " CHANGED TO");
  158. /*
  159. * Fetch and update department budgets.
  160. */
  161. while ((fetch_stat = isc_dsql_fetch(status, &stmt, 1, osqlda)) == 0)
  162. {
  163. /* Determine the increase percentage. */
  164. proj_id[PROJLEN] = '\0';
  165. dept_no[DEPTLEN] = '\0';
  166. printf("%-15s%-10s%15.2f", proj_id, dept_no, budget);
  167. budget = budget + budget * increase_factor(budget);
  168. printf("%15.2f\n", budget);
  169. /* Increase the budget. */
  170. isc_dsql_exec_immed2(status, &DB, &trans, 0, upd_str, 1, isqlda, NULL);
  171. if (isc_sqlcode(status) == -625)
  172. {
  173. printf("\tExceeded budget limit -- not updated.\n");
  174. continue;
  175. }
  176. else
  177. isc_print_status(status);
  178. }
  179. if (fetch_stat != 100L)
  180. {
  181. ERREXIT(status, 1)
  182. }
  183. if (isc_dsql_free_statement(status, &stmt, DSQL_close))
  184. {
  185. ERREXIT(status, 1)
  186. }
  187. if (isc_rollback_transaction(status, &trans))
  188. {
  189. ERREXIT(status, 1)
  190. }
  191. if (isc_detach_database(status, &DB))
  192. {
  193. ERREXIT(status, 1)
  194. }
  195. free(osqlda);
  196. free(isqlda);
  197. return 0;
  198. }
  199. /*
  200. * Determine a percent increase for the department's budget.
  201. */
  202. float increase_factor (double budget)
  203. {
  204. if (budget < 100000L)
  205. return (float)0.15;
  206. else if (budget < 500000L)
  207. return (float)0.10;
  208. else
  209. return (float)0.5;
  210. }