2
0

api16.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /********************************************************************8
  2. **
  3. ** Program type: API
  4. **
  5. ** Description: This program does an asynchronous event wait
  6. ** on a trigger set up in employee.sales.
  7. ** Somebody must add a new sales order to alert
  8. ** this program. That role can be accomplished
  9. ** by running programs stat12t or api16t at the
  10. ** same time.
  11. **
  12. ** When the event is fired, this program selects
  13. ** back any new records and updates (current) those
  14. ** records to status "open". The entire program runs
  15. ** in a single read-committed (wait, no version)
  16. ** transaction, so transaction doesn't need to be started
  17. ** after an event.
  18. * The contents of this file are subject to the Interbase Public
  19. * License Version 1.0 (the "License"); you may not use this file
  20. * except in compliance with the License. You may obtain a copy
  21. * of the License at http://www.Inprise.com/IPL.html
  22. *
  23. * Software distributed under the License is distributed on an
  24. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  25. * or implied. See the License for the specific language governing
  26. * rights and limitations under the License.
  27. *
  28. * The Original Code was created by Inprise Corporation
  29. * and its predecessors. Portions created by Inprise Corporation are
  30. * Copyright (C) Inprise Corporation.
  31. *
  32. * All Rights Reserved.
  33. * Contributor(s): ______________________________________.
  34. */
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include "example.h"
  39. #include <ibase.h>
  40. /* Sleep for Windows is a stupid loop with I/O */
  41. #if defined _MSC_VER
  42. #include <windows.h>
  43. #define SLEEP(x) Sleep(x * 1000 )
  44. #else
  45. #define SLEEP(x) sleep(x)
  46. #endif
  47. short event_flag = 0;
  48. void ast_routine (void *, USHORT, const UCHAR *);
  49. int main(int argc, char** argv)
  50. {
  51. isc_db_handle DB = NULL; /* database handle */
  52. isc_tr_handle trans = NULL; /* transaction handle */
  53. isc_stmt_handle stmt = NULL; /* transaction handle */
  54. ISC_STATUS_ARRAY status; /* status vector */
  55. char * event_buffer;
  56. char * result_buffer;
  57. long event_id;
  58. short length;
  59. char dbname[128];
  60. char po_number[9];
  61. XSQLDA * sqlda;
  62. short nullind = 0;
  63. char query[128], update[128];
  64. long count[2], i = 0;
  65. ISC_STATUS_ARRAY Vector;
  66. char ids[2][15];
  67. int first = 1;
  68. int ret = 0;
  69. /* Transaction parameter block for read committed */
  70. static char isc_tpb[5] = {isc_tpb_version1,
  71. isc_tpb_write,
  72. isc_tpb_read_committed,
  73. isc_tpb_wait,
  74. isc_tpb_no_rec_version};
  75. if (argc > 1)
  76. strcpy(dbname, argv[1]);
  77. else
  78. strcpy(dbname, "employee.fdb");
  79. strcpy (ids[0], "new_order");
  80. strcpy (ids[1], "change_order");
  81. count[0] = 0;
  82. count[1] = 0;
  83. sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
  84. sqlda->sqln = 1;
  85. sqlda->version = 1;
  86. sqlda->sqlvar[0].sqldata = po_number;
  87. sqlda->sqlvar[0].sqlind = &nullind;
  88. if (isc_attach_database (status, 0, dbname, &DB, 0, NULL))
  89. {ERREXIT(status, 1)}
  90. /* SET TRANSACTION ISOLATION LEVEL READ COMMITTED */
  91. if (isc_start_transaction (status, &trans, 1, &DB, 5, isc_tpb))
  92. {ERREXIT(status, 1)}
  93. /* Prepare the query to look at the result tables */
  94. strcpy(query, " SELECT po_number FROM sales \
  95. WHERE order_status = 'new' FOR UPDATE");
  96. /* This is for the update where current of */
  97. strcpy(update,
  98. "UPDATE sales SET order_status = 'open' WHERE CURRENT OF C");
  99. isc_dsql_allocate_statement(status, &DB, &stmt);
  100. if (isc_dsql_prepare(status, &trans, &stmt, 0, query, 1, sqlda))
  101. {ERREXIT(status, 1)};
  102. /* Call the cursor "C" */
  103. isc_dsql_set_cursor_name(status, &stmt, "C", 0);
  104. /* Allocate an event block and initialize its values
  105. ** This will wait on two named events
  106. */
  107. length = (short) isc_event_block((char **) &event_buffer,
  108. (char **) &result_buffer,
  109. 2, ids[0], ids[1], 0);
  110. /* Request the server to notify us of our events of interest.
  111. ** When one of the two named events is triggered, the ast_routine
  112. ** will be called with event_buffer, an updated buffer and length
  113. ** que_events returns ast_returns value
  114. */
  115. if(isc_que_events(status, &DB, &event_id, length,
  116. event_buffer, ast_routine, result_buffer))
  117. {ERREXIT(status, 1)}
  118. while (!ret)
  119. {
  120. i++;
  121. /* If the event was triggered, reset the buffer and re-queue */
  122. if (event_flag)
  123. {
  124. /* Check for first ast_call. isc_que_events fires
  125. each event to get processing started */
  126. if ( first )
  127. {
  128. first = 0;
  129. event_flag = 0;
  130. }
  131. else
  132. {
  133. event_flag = 0;
  134. /* event_counts will compare the various events
  135. ** listed in the two buffers and update the
  136. ** appropriate count_array elements with the difference
  137. ** in the counts in the two buffers.
  138. */
  139. isc_event_counts(Vector, length, (char *) event_buffer,
  140. (char *) result_buffer);
  141. /* Look through the count array */
  142. count[0] += Vector[0];
  143. count[1] += Vector[1];
  144. /* Select query to look at triggered events */
  145. if (isc_dsql_execute(status, &trans, &stmt, 1, NULL))
  146. {ERREXIT(status, 1)}
  147. while (!isc_dsql_fetch(status, &stmt, 1, sqlda))
  148. {
  149. po_number[8] = 0;
  150. printf("api16: %s\n", po_number);
  151. /* exit on processing the last example record*/
  152. if (!strncmp(po_number, "VNEW4", 5))
  153. ret = 1;
  154. /* Update current row */
  155. if(isc_dsql_execute_immediate(status, &DB,
  156. &trans, 0, update, 1, NULL))
  157. {ERREXIT(status, 1)}
  158. }
  159. /* Close cursor */
  160. isc_dsql_free_statement(status, &stmt, DSQL_close);
  161. }
  162. /* Re-queue for the next event */
  163. if (isc_que_events(status, &DB, &event_id, length,
  164. event_buffer, ast_routine, result_buffer))
  165. {ERREXIT(status, 1)}
  166. }
  167. /* This does not block, but as a sample program there is nothing
  168. ** else for us to do, so we will take a nap
  169. */
  170. SLEEP(1);
  171. }
  172. isc_commit_transaction(status, &trans);
  173. isc_detach_database (status, &DB);
  174. printf("Event complete, exiting\n");
  175. free( sqlda);
  176. return 0;
  177. }
  178. /*
  179. ** The called routine is always called with these three buffers. Any
  180. ** event will land us here . PLus we get called once when the
  181. ** program first starts.
  182. */
  183. void ast_routine(void *result, USHORT length, /*const*/ UCHAR *updated)
  184. {
  185. /* Set the global event flag */
  186. event_flag++;
  187. printf("ast routine was called\n");
  188. /* Copy the updated buffer to the result buffer */
  189. while (length--)
  190. *(UCHAR*)result++ = *updated++;
  191. }