soci-firebird.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. //
  2. // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. //
  8. #ifndef SOCI_FIREBIRD_H_INCLUDED
  9. #define SOCI_FIREBIRD_H_INCLUDED
  10. #include <soci/soci-platform.h>
  11. #ifdef SOCI_FIREBIRD_SOURCE
  12. # define SOCI_FIREBIRD_DECL SOCI_DECL_EXPORT
  13. #else
  14. # define SOCI_FIREBIRD_DECL SOCI_DECL_IMPORT
  15. #endif
  16. #ifdef _WIN32
  17. #include <ciso646> // To understand and/or/not on MSVC9
  18. #endif
  19. #include <soci/soci-backend.h>
  20. #include <ibase.h> // FireBird
  21. #include <cstdlib>
  22. #include <vector>
  23. #include <string>
  24. #include <cstdint>
  25. namespace soci
  26. {
  27. std::size_t const stat_size = 20;
  28. // size of buffer for error messages. All examples use this value.
  29. // Anyone knows, where it is stated that 512 bytes is enough ?
  30. std::size_t const SOCI_FIREBIRD_ERRMSG = 512;
  31. class SOCI_FIREBIRD_DECL firebird_soci_error : public soci_error
  32. {
  33. public:
  34. firebird_soci_error(std::string const & msg,
  35. ISC_STATUS const * status = 0);
  36. ~firebird_soci_error() noexcept override {};
  37. std::vector<ISC_STATUS> status_;
  38. };
  39. enum BuffersType
  40. {
  41. eStandard, eVector
  42. };
  43. struct firebird_blob_backend;
  44. struct firebird_statement_backend;
  45. struct firebird_standard_into_type_backend : details::standard_into_type_backend
  46. {
  47. firebird_standard_into_type_backend(firebird_statement_backend &st)
  48. : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0)
  49. {}
  50. void define_by_pos(int &position,
  51. void *data, details::exchange_type type) override;
  52. void pre_fetch() override;
  53. void post_fetch(bool gotData, bool calledFromFetch,
  54. indicator *ind) override;
  55. void clean_up() override;
  56. firebird_statement_backend &statement_;
  57. virtual void exchangeData();
  58. void *data_;
  59. details::exchange_type type_;
  60. int position_;
  61. char *buf_;
  62. short indISCHolder_;
  63. };
  64. struct firebird_vector_into_type_backend : details::vector_into_type_backend
  65. {
  66. firebird_vector_into_type_backend(firebird_statement_backend &st)
  67. : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0)
  68. {}
  69. void define_by_pos(int &position,
  70. void *data, details::exchange_type type) override;
  71. void pre_fetch() override;
  72. void post_fetch(bool gotData, indicator *ind) override;
  73. void resize(std::size_t sz) override;
  74. std::size_t size() override;
  75. void clean_up() override;
  76. firebird_statement_backend &statement_;
  77. virtual void exchangeData(std::size_t row);
  78. void *data_;
  79. details::exchange_type type_;
  80. int position_;
  81. char *buf_;
  82. short indISCHolder_;
  83. };
  84. struct firebird_standard_use_type_backend : details::standard_use_type_backend
  85. {
  86. firebird_standard_use_type_backend(firebird_statement_backend &st)
  87. : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0),
  88. blob_(NULL)
  89. {}
  90. void bind_by_pos(int &position,
  91. void *data, details::exchange_type type, bool readOnly) override;
  92. void bind_by_name(std::string const &name,
  93. void *data, details::exchange_type type, bool readOnly) override;
  94. void pre_use(indicator const *ind) override;
  95. void post_use(bool gotData, indicator *ind) override;
  96. void clean_up() override;
  97. firebird_statement_backend &statement_;
  98. virtual void exchangeData();
  99. void *data_;
  100. details::exchange_type type_;
  101. int position_;
  102. char *buf_;
  103. short indISCHolder_;
  104. private:
  105. // Allocate a temporary blob, fill it with the data from the provided
  106. // string and copy its ID into buf_.
  107. void copy_to_blob(const std::string& in);
  108. // This is used for types mapping to CLOB.
  109. firebird_blob_backend* blob_;
  110. };
  111. struct firebird_vector_use_type_backend : details::vector_use_type_backend
  112. {
  113. firebird_vector_use_type_backend(firebird_statement_backend &st)
  114. : statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0),
  115. blob_(NULL)
  116. {}
  117. void bind_by_pos(int &position,
  118. void *data, details::exchange_type type) override;
  119. void bind_by_name(std::string const &name,
  120. void *data, details::exchange_type type) override;
  121. void pre_use(indicator const *ind) override;
  122. std::size_t size() override;
  123. void clean_up() override;
  124. firebird_statement_backend &statement_;
  125. virtual void exchangeData(std::size_t row);
  126. void *data_;
  127. details::exchange_type type_;
  128. int position_;
  129. indicator const *inds_;
  130. char *buf_;
  131. short indISCHolder_;
  132. private:
  133. // Allocate a temporary blob, fill it with the data from the provided
  134. // string and copy its ID into buf_.
  135. void copy_to_blob(const std::string &in);
  136. // This is used for types mapping to CLOB.
  137. firebird_blob_backend *blob_;
  138. };
  139. struct firebird_session_backend;
  140. struct firebird_statement_backend : details::statement_backend
  141. {
  142. firebird_statement_backend(firebird_session_backend &session);
  143. void alloc() override;
  144. void clean_up() override;
  145. void prepare(std::string const &query,
  146. details::statement_type eType) override;
  147. exec_fetch_result execute(int number) override;
  148. exec_fetch_result fetch(int number) override;
  149. long long get_affected_rows() override;
  150. int get_number_of_rows() override;
  151. std::string get_parameter_name(int index) const override;
  152. std::string rewrite_for_procedure_call(std::string const &query) override;
  153. int prepare_for_describe() override;
  154. void describe_column(int colNum,
  155. db_type &dbtype,
  156. std::string &columnName) override;
  157. firebird_standard_into_type_backend * make_into_type_backend() override;
  158. firebird_standard_use_type_backend * make_use_type_backend() override;
  159. firebird_vector_into_type_backend * make_vector_into_type_backend() override;
  160. firebird_vector_use_type_backend * make_vector_use_type_backend() override;
  161. firebird_session_backend &session_;
  162. isc_stmt_handle stmtp_;
  163. XSQLDA * sqldap_;
  164. XSQLDA * sqlda2p_;
  165. bool boundByName_;
  166. bool boundByPos_;
  167. friend struct firebird_vector_into_type_backend;
  168. friend struct firebird_standard_into_type_backend;
  169. friend struct firebird_vector_use_type_backend;
  170. friend struct firebird_standard_use_type_backend;
  171. protected:
  172. int rowsFetched_;
  173. bool endOfRowSet_;
  174. long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
  175. virtual void exchangeData(bool gotData, int row);
  176. virtual void prepareSQLDA(XSQLDA ** sqldap, short size = 10);
  177. virtual void rewriteQuery(std::string const & query,
  178. std::vector<char> & buffer);
  179. virtual void rewriteParameters(std::string const & src,
  180. std::vector<char> & dst);
  181. BuffersType intoType_;
  182. BuffersType useType_;
  183. std::vector<std::vector<indicator> > inds_;
  184. std::vector<void*> intos_;
  185. std::vector<void*> uses_;
  186. // named parameters
  187. std::map <std::string, int> names_;
  188. bool procedure_;
  189. };
  190. struct firebird_blob_backend : details::blob_backend
  191. {
  192. firebird_blob_backend(firebird_session_backend &session);
  193. ~firebird_blob_backend() override;
  194. std::size_t get_len() override;
  195. std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
  196. std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
  197. std::size_t append(const void *buf, std::size_t toWrite) override;
  198. void trim(std::size_t newLen) override;
  199. // Writes the current data into the database by allocating a new BLOB
  200. // object for it.
  201. //
  202. // Returns The ID of the newly created BLOB object
  203. ISC_QUAD save_to_db();
  204. void assign(ISC_QUAD const & bid);
  205. private:
  206. void open();
  207. long getBLOBInfo();
  208. void load();
  209. void writeBuffer(std::size_t offset, void const * buf,
  210. std::size_t toWrite);
  211. void closeBlob();
  212. firebird_session_backend &session_;
  213. ISC_QUAD blob_id_;
  214. // BLOB id was fetched from database (true)
  215. // or this is new BLOB
  216. bool from_db_;
  217. isc_blob_handle blob_handle_;
  218. // buffer for BLOB data
  219. std::vector<std::uint8_t> data_;
  220. bool loaded_;
  221. long max_seg_size_;
  222. };
  223. struct firebird_session_backend : details::session_backend
  224. {
  225. firebird_session_backend(connection_parameters const & parameters);
  226. ~firebird_session_backend() override;
  227. bool is_connected() override;
  228. void begin() override;
  229. void commit() override;
  230. void rollback() override;
  231. bool get_next_sequence_value(session & s,
  232. std::string const & sequence, long long & value) override;
  233. std::string get_dummy_from_table() const override { return "rdb$database"; }
  234. std::string get_backend_name() const override { return "firebird"; }
  235. void cleanUp();
  236. firebird_statement_backend * make_statement_backend() override;
  237. details::rowid_backend* make_rowid_backend() override;
  238. firebird_blob_backend * make_blob_backend() override;
  239. bool get_option_decimals_as_strings() { return decimals_as_strings_; }
  240. // Returns the pointer to the current transaction handle, starting a new
  241. // transaction if necessary.
  242. //
  243. // The returned pointer should
  244. isc_tr_handle* current_transaction();
  245. isc_db_handle dbhp_;
  246. private:
  247. isc_tr_handle trhp_;
  248. bool decimals_as_strings_;
  249. };
  250. struct firebird_backend_factory : backend_factory
  251. {
  252. firebird_backend_factory() {}
  253. firebird_session_backend * make_session(
  254. connection_parameters const & parameters) const override;
  255. };
  256. extern SOCI_FIREBIRD_DECL firebird_backend_factory const firebird;
  257. extern "C"
  258. {
  259. // for dynamic backend loading
  260. SOCI_FIREBIRD_DECL backend_factory const * factory_firebird();
  261. SOCI_FIREBIRD_DECL void register_factory_firebird();
  262. } // extern "C"
  263. } // namespace soci
  264. #endif // SOCI_FIREBIRD_H_INCLUDED