12.batch_isc.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * PROGRAM: Object oriented API samples.
  3. * MODULE: 12.batch_isc.cpp
  4. * DESCRIPTION: A sample of using Batch interface.
  5. *
  6. * Example for the following interfaces:
  7. * IUtil - get IStatement/ITransaction by handle
  8. * IBatch - interface to work with FB batches
  9. * IBatchCompletionState - contains result of batch execution
  10. *
  11. * c++ 12.batch_isc.cpp -lfbclient
  12. *
  13. * The contents of this file are subject to the Initial
  14. * Developer's Public License Version 1.0 (the "License");
  15. * you may not use this file except in compliance with the
  16. * License. You may obtain a copy of the License at
  17. * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
  18. *
  19. * Software distributed under the License is distributed AS IS,
  20. * WITHOUT WARRANTY OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing rights
  22. * and limitations under the License.
  23. *
  24. * The Original Code was created by Alexander Peshkoff
  25. * for the Firebird Open Source RDBMS project.
  26. *
  27. * Copyright (c) 2018 Alexander Peshkoff <[email protected]>
  28. * and all contributors signed below.
  29. *
  30. * All Rights Reserved.
  31. * Contributor(s): ______________________________________.
  32. */
  33. #include "ifaceExamples.h"
  34. #include <firebird/Message.h>
  35. static IMaster* master = fb_get_master_interface();
  36. // output error message to user
  37. static void errPrint(IStatus* status)
  38. {
  39. isc_print_status(status->getErrors());
  40. }
  41. static void raiseError(ThrowStatusWrapper& status, ISC_STATUS *vector)
  42. {
  43. throw FbException(&status, vector);
  44. }
  45. // BatchCompletionState printer - prints all what we know about completed batch
  46. static void print_cs(ThrowStatusWrapper& status, IBatchCompletionState* cs, IUtil* utl)
  47. {
  48. unsigned p = 0;
  49. IStatus* s2 = NULL;
  50. bool pr1 = false, pr2 = false;
  51. // 1. Print per-message state info
  52. unsigned upcount = cs->getSize(&status);
  53. unsigned unk = 0, succ = 0;
  54. for (p = 0; p < upcount; ++p)
  55. {
  56. int s = cs->getState(&status, p);
  57. switch (s)
  58. {
  59. case IBatchCompletionState::EXECUTE_FAILED:
  60. if (!pr1)
  61. {
  62. printf("Message Status\n");
  63. pr1 = true;
  64. }
  65. printf("%5u Execute failed\n", p);
  66. break;
  67. case IBatchCompletionState::SUCCESS_NO_INFO:
  68. ++unk;
  69. break;
  70. default:
  71. if (!pr1)
  72. {
  73. printf("Message Status\n");
  74. pr1 = true;
  75. }
  76. printf("%5u Updated %d record(s)\n", p, s);
  77. ++succ;
  78. break;
  79. }
  80. }
  81. printf("Summary: total=%u success=%u success(but no update info)=%u\n", upcount, succ, unk);
  82. // 2. Print detailed errors (if exist) for messages
  83. s2 = master->getStatus();
  84. for(p = 0; (p = cs->findError(&status, p)) != IBatchCompletionState::NO_MORE_ERRORS; ++p)
  85. {
  86. try
  87. {
  88. cs->getStatus(&status, s2, p);
  89. char text[1024];
  90. utl->formatStatus(text, sizeof(text) - 1, s2);
  91. text[sizeof(text) - 1] = 0;
  92. if (!pr2)
  93. {
  94. printf("\nDetailed errors status:\n");
  95. pr2 = true;
  96. }
  97. printf("Message %u: %s\n", p, text);
  98. }
  99. catch (const FbException& error)
  100. {
  101. // handle error
  102. fprintf(stderr, "\nError describing message %u\n", p);
  103. errPrint(error.getStatus());
  104. fprintf(stderr, "\n");
  105. }
  106. }
  107. if (s2)
  108. s2->dispose();
  109. }
  110. int main()
  111. {
  112. int rc = 0;
  113. // set default password if none specified in environment
  114. setenv("ISC_USER", "sysdba", 0);
  115. setenv("ISC_PASSWORD", "masterkey", 0);
  116. // With ThrowStatusWrapper passed as status interface FbException will be thrown on error
  117. ThrowStatusWrapper status(master->getStatus());
  118. ISC_STATUS_ARRAY st;
  119. isc_db_handle db = 0;
  120. isc_tr_handle tr = 0;
  121. isc_stmt_handle stmt = 0;
  122. isc_blob_handle blb = 0;
  123. // Declare pointers to required interfaces
  124. /*IProvider* prov = master->getDispatcher();
  125. IAttachment* att = NULL;*/
  126. IUtil* utl = master->getUtilInterface();
  127. IStatement* statement = NULL;
  128. ITransaction* tra = NULL;
  129. IBatch* batch = NULL;
  130. IBatchCompletionState* cs = NULL;
  131. IXpbBuilder* pb = NULL;
  132. unsigned char streamBuf[10240]; // big enough for demo
  133. unsigned char* stream = NULL;
  134. try
  135. {
  136. // attach employee db
  137. if (isc_attach_database(st, 0, "employee", &db, 0, NULL))
  138. raiseError(status, st);
  139. isc_tr_handle tr = 0;
  140. if (isc_start_transaction(st, &tr, 1, &db, 0, NULL))
  141. raiseError(status, st);
  142. // cleanup
  143. const char* cleanSql = "delete from project where proj_id like 'BAT%'";
  144. if (isc_dsql_execute_immediate(st, &db, &tr, 0, cleanSql, 3, NULL))
  145. raiseError(status, st);
  146. if (isc_dsql_allocate_statement(st, &db, &stmt))
  147. raiseError(status, st);
  148. // get transaction interface
  149. if (fb_get_transaction_interface(st, &tra, &tr))
  150. raiseError(status, st);
  151. //
  152. printf("\nPart 1. BLOB created using IBlob interface.\n");
  153. //
  154. // prepare statement
  155. const char* sqlStmt1 = "insert into project(proj_id, proj_name) values(?, ?)";
  156. if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt1, 3, NULL))
  157. raiseError(status, st);
  158. // and get it's interface
  159. if (fb_get_statement_interface(st, &statement, &stmt))
  160. raiseError(status, st);
  161. // Message to store in a table
  162. FB_MESSAGE(Msg1, ThrowStatusWrapper,
  163. (FB_VARCHAR(5), id)
  164. (FB_VARCHAR(10), name)
  165. ) project1(&status, master);
  166. project1.clear();
  167. IMessageMetadata* meta = project1.getMetadata();
  168. // set batch parameters
  169. pb = utl->getXpbBuilder(&status, IXpbBuilder::BATCH, NULL, 0);
  170. // collect per-message statistics
  171. pb->insertInt(&status, IBatch::TAG_RECORD_COUNTS, 1);
  172. // create batch
  173. batch = statement->createBatch(&status, meta,
  174. pb->getBufferLength(&status), pb->getBuffer(&status));
  175. // fill batch with data record by record
  176. project1->id.set("BAT11");
  177. project1->name.set("SNGL_REC");
  178. batch->add(&status, 1, project1.getData());
  179. project1->id.set("BAT12");
  180. project1->name.set("SNGL_REC2");
  181. batch->add(&status, 1, project1.getData());
  182. // execute it
  183. cs = batch->execute(&status, tra);
  184. print_cs(status, cs, utl);
  185. // close batch
  186. batch->release();
  187. batch = NULL;
  188. // unprepare statement
  189. statement->release();
  190. statement = NULL;
  191. if (isc_dsql_free_statement(st, &stmt, DSQL_unprepare))
  192. raiseError(status, st);
  193. //
  194. printf("\nPart 2. BLOB created using isc_create_blob.\n");
  195. //
  196. // prepare statement
  197. const char* sqlStmt2 = "insert into project(proj_id, proj_name, proj_desc) values(?, ?, ?)";
  198. if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt2, 3, NULL))
  199. raiseError(status, st);
  200. // and get it's interface
  201. if (fb_get_statement_interface(st, &statement, &stmt))
  202. raiseError(status, st);
  203. // Message to store in a table
  204. FB_MESSAGE(Msg2, ThrowStatusWrapper,
  205. (FB_VARCHAR(5), id)
  206. (FB_VARCHAR(10), name)
  207. (FB_BLOB, desc)
  208. ) project2(&status, master);
  209. project2.clear();
  210. meta = project2.getMetadata();
  211. // set batch parameters
  212. pb->clear(&status);
  213. // enable blobs processing - IDs generated by firebird engine
  214. pb->insertInt(&status, IBatch::TAG_BLOB_POLICY, IBatch::BLOB_ID_ENGINE);
  215. // create batch
  216. batch = statement->createBatch(&status, meta,
  217. pb->getBufferLength(&status), pb->getBuffer(&status));
  218. // create blob
  219. ISC_QUAD realId;
  220. if (isc_create_blob(st, &db, &tr, &blb, &realId))
  221. raiseError(status, st);
  222. const char* text = "Blob created using traditional API";
  223. if (isc_put_segment(st, &blb, strlen(text), text))
  224. raiseError(status, st);
  225. if (isc_close_blob(st, &blb))
  226. raiseError(status, st);
  227. // add message
  228. project2->id.set("BAT38");
  229. project2->name.set("FRGN_BLB");
  230. batch->registerBlob(&status, &realId, &project2->desc);
  231. batch->add(&status, 1, project2.getData());
  232. // execute it
  233. cs = batch->execute(&status, tra);
  234. print_cs(status, cs, utl);
  235. // close batch
  236. batch->release();
  237. batch = NULL;
  238. // unprepare statement
  239. statement->release();
  240. statement = NULL;
  241. if (isc_dsql_free_statement(st, &stmt, DSQL_drop))
  242. raiseError(status, st);
  243. // cleanup
  244. tra->release();
  245. tra = NULL;
  246. if (isc_commit_transaction (st, &tr))
  247. raiseError(status, st);
  248. if (isc_detach_database(st, &db))
  249. raiseError(status, st);
  250. }
  251. catch (const FbException& error)
  252. {
  253. // handle error
  254. rc = 1;
  255. errPrint(error.getStatus());
  256. }
  257. // release interfaces after error caught
  258. if (cs)
  259. cs->dispose();
  260. if (batch)
  261. batch->release();
  262. if (tra)
  263. tra->release();
  264. if (statement)
  265. statement->release();
  266. // close handles if not closed
  267. if (blb)
  268. isc_cancel_blob(st, &blb);
  269. if (stmt)
  270. isc_dsql_free_statement(st, &stmt, DSQL_close);
  271. if (tr)
  272. isc_rollback_transaction (st, &tr);
  273. if (db)
  274. isc_detach_database(st, &db);
  275. // cleanup
  276. if (pb)
  277. pb->dispose();
  278. status.dispose();
  279. return rc;
  280. }