03.select.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * PROGRAM: Object oriented API samples.
  3. * MODULE: 03.select.cpp
  4. * DESCRIPTION: A sample of running SELECT statement without parameters.
  5. * Prints string fields in a table, coercing VARCHAR to CHAR.
  6. * Learns how to coerce output data in prepared statement
  7. * and execute it.
  8. *
  9. * Example for the following interfaces:
  10. *
  11. * IStatement - SQL statement execution
  12. * IMessageMetadata - describe input and output data format
  13. * IResultSet - fetch data returned by statement after execution
  14. *
  15. * The contents of this file are subject to the Initial
  16. * Developer's Public License Version 1.0 (the "License");
  17. * you may not use this file except in compliance with the
  18. * License. You may obtain a copy of the License at
  19. * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
  20. *
  21. * Software distributed under the License is distributed AS IS,
  22. * WITHOUT WARRANTY OF ANY KIND, either express or implied.
  23. * See the License for the specific language governing rights
  24. * and limitations under the License.
  25. *
  26. * The Original Code was created by Alexander Peshkoff
  27. * for the Firebird Open Source RDBMS project.
  28. *
  29. * Copyright (c) 2013 Alexander Peshkoff <[email protected]>
  30. * and all contributors signed below.
  31. *
  32. * All Rights Reserved.
  33. * Contributor(s): ______________________________________.
  34. */
  35. #include "ifaceExamples.h"
  36. static IMaster* master = fb_get_master_interface();
  37. int main()
  38. {
  39. int rc = 0;
  40. // set default password if none specified in environment
  41. setenv("ISC_USER", "sysdba", 0);
  42. setenv("ISC_PASSWORD", "masterkey", 0);
  43. // status vector and main dispatcher
  44. ThrowStatusWrapper status(master->getStatus());
  45. IProvider* prov = master->getDispatcher();
  46. IUtil* utl = master->getUtilInterface();
  47. // declare pointers to required interfaces
  48. IAttachment* att = NULL;
  49. ITransaction* tra = NULL;
  50. IStatement* stmt = NULL;
  51. IMessageMetadata* meta = NULL;
  52. IMetadataBuilder* builder = NULL;
  53. IXpbBuilder* tpb = NULL;
  54. // Interface provides access to data returned by SELECT statement
  55. IResultSet* curs = NULL;
  56. try
  57. {
  58. // attach employee db
  59. att = prov->attachDatabase(&status, "employee", 0, NULL);
  60. // start read only transaction
  61. tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0);
  62. tpb->insertTag(&status, isc_tpb_read_committed);
  63. tpb->insertTag(&status, isc_tpb_no_rec_version);
  64. tpb->insertTag(&status, isc_tpb_wait);
  65. tpb->insertTag(&status, isc_tpb_read);
  66. tra = att->startTransaction(&status, tpb->getBufferLength(&status), tpb->getBuffer(&status));
  67. // prepare statement
  68. stmt = att->prepare(&status, tra, 0, "select last_name, first_name, phone_ext from phone_list "
  69. "where location = 'Monterey' order by last_name, first_name",
  70. SAMPLES_DIALECT, IStatement::PREPARE_PREFETCH_METADATA);
  71. // get list of columns
  72. meta = stmt->getOutputMetadata(&status);
  73. builder = meta->getBuilder(&status);
  74. unsigned cols = meta->getCount(&status);
  75. // struct to cache received metadata
  76. struct MyField
  77. {
  78. const char* name;
  79. unsigned length, offset;
  80. };
  81. MyField* fields = new MyField[cols];
  82. memset(fields, 0, sizeof(MyField) * cols);
  83. // parse columns list & coerce datatype(s)
  84. for (unsigned j = 0; j < cols; ++j)
  85. {
  86. unsigned t = meta->getType(&status, j);
  87. if (t == SQL_VARYING || t == SQL_TEXT)
  88. {
  89. builder->setType(&status, j, SQL_TEXT);
  90. fields[j].name = meta->getField(&status, j);
  91. }
  92. }
  93. // release automatically created metadata
  94. // metadata is not database object, therefore no specific call to close it
  95. meta->release();
  96. // get metadata with coerced datatypes
  97. meta = builder->getMetadata(&status);
  98. // builder not needed any more
  99. builder->release();
  100. builder = NULL;
  101. // now we may also get offsets info
  102. for (unsigned j = 0; j < cols; ++j)
  103. {
  104. if (fields[j].name)
  105. {
  106. fields[j].length = meta->getLength(&status, j);
  107. fields[j].offset = meta->getOffset(&status, j);
  108. }
  109. }
  110. // open cursor
  111. curs = stmt->openCursor(&status, tra, NULL, NULL, meta, 0);
  112. // allocate output buffer
  113. unsigned l = meta->getMessageLength(&status);
  114. unsigned char* buffer = new unsigned char[l];
  115. // fetch records from cursor and print them
  116. for (int line = 0; curs->fetchNext(&status, buffer) == IStatus::RESULT_OK; ++line)
  117. {
  118. if (line % 10 == 0)
  119. {
  120. printf("\n");
  121. for (unsigned j = 0; j < cols; ++j)
  122. {
  123. if (fields[j].name)
  124. {
  125. printf("%-*.*s ", fields[j].length, fields[j].length, fields[j].name);
  126. }
  127. }
  128. printf("\n");
  129. }
  130. for (unsigned j = 0; j < cols; ++j)
  131. {
  132. if (fields[j].name)
  133. {
  134. printf("%*.*s ", fields[j].length, fields[j].length, buffer + fields[j].offset);
  135. }
  136. }
  137. printf("\n");
  138. }
  139. printf("\n");
  140. // close interfaces
  141. curs->close(&status);
  142. curs = NULL;
  143. stmt->free(&status);
  144. stmt = NULL;
  145. meta->release();
  146. meta = NULL;
  147. tra->commit(&status);
  148. tra = NULL;
  149. att->detach(&status);
  150. att = NULL;
  151. }
  152. catch (const FbException& error)
  153. {
  154. // handle error
  155. rc = 1;
  156. char buf[256];
  157. master->getUtilInterface()->formatStatus(buf, sizeof(buf), error.getStatus());
  158. fprintf(stderr, "%s\n", buf);
  159. }
  160. // release interfaces after error caught
  161. if (meta)
  162. meta->release();
  163. if (builder)
  164. builder->release();
  165. if (curs)
  166. curs->release();
  167. if (stmt)
  168. stmt->release();
  169. if (tra)
  170. tra->release();
  171. if (att)
  172. att->release();
  173. if (tpb)
  174. tpb->dispose();
  175. prov->release();
  176. status.dispose();
  177. return rc;
  178. }