soci-odbc.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
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_ODBC_H_INCLUDED
9 #define SOCI_ODBC_H_INCLUDED
10 
11 #ifdef _WIN32
12 # ifdef SOCI_DLL
13 # ifdef SOCI_ODBC_SOURCE
14 # define SOCI_ODBC_DECL __declspec(dllexport)
15 # else
16 # define SOCI_ODBC_DECL __declspec(dllimport)
17 # endif // SOCI_ODBC_SOURCE
18 # endif // SOCI_DLL
19 #endif // _WIN32
20 //
21 // If SOCI_ODBC_DECL isn't defined yet define it now
22 #ifndef SOCI_ODBC_DECL
23 # define SOCI_ODBC_DECL
24 #endif
25 
26 #include <vector>
27 #include <sstream>
28 #include <soci-backend.h>
29 #if defined(_MSC_VER) || defined(__MINGW32__)
30 #include <soci-platform.h>
31 #include <windows.h>
32 #endif
33 #include <sqlext.h> // ODBC
34 #include <string.h> // strcpy()
35 
36 namespace soci
37 {
38 
39  // TODO: Do we want to make it a part of public interface? --mloskot
40 namespace details
41 {
42  std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024;
43 }
44 
45 // Option allowing to specify the "driver completion" parameter of
46 // SQLDriverConnect(). Its possible values are the same as the allowed values
47 // for this parameter in the official ODBC, i.e. one of SQL_DRIVER_XXX (in
48 // string form as all options are strings currently).
50 
52 
53 // Helper of into and use backends.
55 {
56 protected:
58  : statement_(st) {}
59 
60  // Check if we need to pass 64 bit integers as strings to the database as
61  // some drivers don't support them directly.
62  inline bool use_string_for_bigint() const;
63 
64  // If we do need to use strings for 64 bit integers, this constant defines
65  // the maximal string length needed.
66  enum
67  {
68  // This is the length of decimal representation of UINT64_MAX + 1.
69  max_bigint_length = 21
70  };
71 
73 };
74 
77 {
79  : odbc_standard_type_backend_base(st), buf_(0)
80  {}
81 
82  virtual void define_by_pos(int &position,
83  void *data, details::exchange_type type);
84 
85  virtual void pre_fetch();
86  virtual void post_fetch(bool gotData, bool calledFromFetch,
87  indicator *ind);
88 
89  virtual void clean_up();
90 
91  char *buf_; // generic buffer
92  void *data_;
94  int position_;
95  SQLSMALLINT odbcType_;
96  SQLLEN valueLen_;
97 };
98 
101 {
103  : odbc_standard_type_backend_base(st), indHolders_(NULL),
104  data_(NULL), buf_(NULL) {}
105 
106  virtual void define_by_pos(int &position,
107  void *data, details::exchange_type type);
108 
109  virtual void pre_fetch();
110  virtual void post_fetch(bool gotData, indicator *ind);
111 
112  virtual void resize(std::size_t sz);
113  virtual std::size_t size();
114 
115  virtual void clean_up();
116 
117  // helper function for preparing indicators
118  // (as part of the define_by_pos)
119  void prepare_indicators(std::size_t size);
120 
121 
122  SQLLEN *indHolders_;
123  std::vector<SQLLEN> indHolderVec_;
124  void *data_;
125  char *buf_; // generic buffer
127  std::size_t colSize_; // size of the string column (used for strings)
128  SQLSMALLINT odbcType_;
129 };
130 
133 {
136  position_(-1), data_(0), buf_(0), indHolder_(0) {}
137 
138  virtual void bind_by_pos(int &position,
139  void *data, details::exchange_type type, bool readOnly);
140  virtual void bind_by_name(std::string const &name,
141  void *data, details::exchange_type type, bool readOnly);
142 
143  virtual void pre_use(indicator const *ind);
144  virtual void post_use(bool gotData, indicator *ind);
145 
146  virtual void clean_up();
147 
148  // Return the pointer to the buffer containing data to be used by ODBC.
149  // This can be either data_ itself or buf_, that is allocated by this
150  // function if necessary.
151  //
152  // Also fill in the size of the data and SQL and C types of it.
153  void* prepare_for_bind(SQLLEN &size,
154  SQLSMALLINT &sqlType, SQLSMALLINT &cType);
155 
157  void *data_;
159  char *buf_;
160  SQLLEN indHolder_;
161 };
162 
165 {
167  : odbc_standard_type_backend_base(st), indHolders_(NULL),
168  data_(NULL), buf_(NULL) {}
169 
170  // helper function for preparing indicators
171  // (as part of the define_by_pos)
172  void prepare_indicators(std::size_t size);
173 
174  // common part for bind_by_pos and bind_by_name
175  void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
176  void bind_helper(int &position,
177  void *data, details::exchange_type type);
178 
179  virtual void bind_by_pos(int &position,
180  void *data, details::exchange_type type);
181  virtual void bind_by_name(std::string const &name,
182  void *data, details::exchange_type type);
183 
184  virtual void pre_use(indicator const *ind);
185 
186  virtual std::size_t size();
187 
188  virtual void clean_up();
189 
190 
191  SQLLEN *indHolders_;
192  std::vector<SQLLEN> indHolderVec_;
193  void *data_;
195  char *buf_; // generic buffer
196  std::size_t colSize_; // size of the string column (used for strings)
197  // used for strings only
198  std::size_t maxSize_;
199 };
200 
201 struct odbc_session_backend;
203 {
205 
206  virtual void alloc();
207  virtual void clean_up();
208  virtual void prepare(std::string const &query,
210 
211  virtual exec_fetch_result execute(int number);
212  virtual exec_fetch_result fetch(int number);
213 
214  virtual long long get_affected_rows();
215  virtual int get_number_of_rows();
216 
217  virtual std::string rewrite_for_procedure_call(std::string const &query);
218 
219  virtual int prepare_for_describe();
220  virtual void describe_column(int colNum, data_type &dtype,
221  std::string &columnName);
222 
223  // helper for defining into vector<string>
224  std::size_t column_size(int position);
225 
226  virtual odbc_standard_into_type_backend * make_into_type_backend();
227  virtual odbc_standard_use_type_backend * make_use_type_backend();
228  virtual odbc_vector_into_type_backend * make_vector_into_type_backend();
229  virtual odbc_vector_use_type_backend * make_vector_use_type_backend();
230 
232  SQLHSTMT hstmt_;
237 
238  long long rowsAffected_; // number of rows affected by the last operation
239 
240  std::string query_;
241  std::vector<std::string> names_; // list of names for named binds
242 
243 };
244 
246 {
248 
250 };
251 
253 {
255 
257 
258  virtual std::size_t get_len();
259  virtual std::size_t read(std::size_t offset, char *buf,
260  std::size_t toRead);
261  virtual std::size_t write(std::size_t offset, char const *buf,
262  std::size_t toWrite);
263  virtual std::size_t append(char const *buf, std::size_t toWrite);
264  virtual void trim(std::size_t newLen);
265 
267 };
268 
270 {
272 
274 
275  virtual void begin();
276  virtual void commit();
277  virtual void rollback();
278 
279  virtual bool get_next_sequence_value(session & s,
280  std::string const & sequence, long & value);
281  virtual bool get_last_insert_id(session & s,
282  std::string const & table, long & value);
283 
284  virtual std::string get_backend_name() const { return "odbc"; }
285 
286  void reset_transaction();
287 
288  void clean_up();
289 
290  virtual odbc_statement_backend * make_statement_backend();
291  virtual odbc_rowid_backend * make_rowid_backend();
292  virtual odbc_blob_backend * make_blob_backend();
293 
295  {
296  prod_uninitialized, // Never returned by get_database_product().
303  prod_unknown = -1
304  };
305 
306  // Determine the type of the database we're connected to.
307  database_product get_database_product();
308 
309  // Return full ODBC connection string.
310  std::string get_connection_string() const { return connection_string_; }
311 
312  SQLHENV henv_;
313  SQLHDBC hdbc_;
314 
315  std::string connection_string_;
317 };
318 
320 {
321  SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1];
322  SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1];
323  SQLINTEGER sqlcode_;
324 
325 public:
326  odbc_soci_error(SQLSMALLINT htype,
327  SQLHANDLE hndl,
328  std::string const & msg)
329  : soci_error(interpret_odbc_error(htype, hndl, msg))
330  {
331  }
332 
333  SQLCHAR const * odbc_error_code() const
334  {
335  return sqlstate_;
336  }
337  SQLINTEGER native_error_code() const
338  {
339  return sqlcode_;
340  }
341  SQLCHAR const * odbc_error_message() const
342  {
343  return message_;
344  }
345 private:
346  std::string interpret_odbc_error(SQLSMALLINT htype, SQLHANDLE hndl, std::string const& msg)
347  {
348  std::ostringstream ss(msg, std::ostringstream::app);
349 
350  const char* socierror = NULL;
351 
352  SQLSMALLINT length, i = 1;
353  switch ( SQLGetDiagRecA(htype, hndl, i, sqlstate_, &sqlcode_,
354  message_, SQL_MAX_MESSAGE_LENGTH + 1,
355  &length) )
356  {
357  case SQL_SUCCESS:
358  // The error message was successfully retrieved.
359  break;
360 
361  case SQL_INVALID_HANDLE:
362  socierror = "[SOCI]: Invalid handle.";
363  break;
364 
365  case SQL_ERROR:
366  socierror = "[SOCI]: SQLGetDiagRec() error.";
367  break;
368 
369  case SQL_SUCCESS_WITH_INFO:
370  socierror = "[SOCI]: Error message too long.";
371  break;
372 
373  case SQL_NO_DATA:
374  socierror = "[SOCI]: No error.";
375  break;
376 
377  default:
378  socierror = "[SOCI]: Unexpected SQLGetDiagRec() return value.";
379  break;
380  }
381 
382  if (socierror)
383  {
384  // Use our own error message if we failed to retrieve the ODBC one.
385  strcpy(reinterpret_cast<char*>(message_), socierror);
386 
387  // Use "General warning" SQLSTATE code.
388  strcpy(reinterpret_cast<char*>(sqlstate_), "01000");
389 
390  sqlcode_ = 0;
391  }
392 
393  ss << ": " << message_ << " (" << sqlstate_ << ")";
394 
395  return ss.str();
396  }
397 };
398 
399 inline bool is_odbc_error(SQLRETURN rc)
400 {
401  if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA)
402  {
403  return true;
404  }
405  else
406  {
407  return false;
408  }
409 }
410 
412 {
413  // Oracle ODBC driver doesn't support SQL_C_[SU]BIGINT data types
414  // (see appendix G.1 of Oracle Database Administrator's reference at
415  // http://docs.oracle.com/cd/B19306_01/server.102/b15658/app_odbc.htm),
416  // so we need a special workaround for this case and we represent 64
417  // bit integers as strings and rely on ODBC driver for transforming
418  // them to SQL_NUMERIC.
419  return statement_.session_.get_database_product()
421 }
422 
424 {
426  virtual odbc_session_backend * make_session(
427  connection_parameters const & parameters) const;
428 };
429 
431 
432 extern "C"
433 {
434 
435 // for dynamic backend loading
438 
439 } // extern "C"
440 
441 } // namespace soci
442 
443 #endif // SOCI_EMPTY_H_INCLUDED
details::exchange_type type_
Definition: soci-odbc.h:194
details::exchange_type type_
Definition: soci-odbc.h:93
SQLCHAR const * odbc_error_message() const
Definition: soci-odbc.h:341
odbc_vector_into_type_backend(odbc_statement_backend &st)
Definition: soci-odbc.h:102
std::size_t const odbc_max_buffer_length
Definition: soci-odbc.h:42
SOCI_ODBC_DECL void register_factory_odbc()
odbc_standard_into_type_backend(odbc_statement_backend &st)
Definition: soci-odbc.h:78
odbc_standard_use_type_backend(odbc_statement_backend &st)
Definition: soci-odbc.h:134
SQLINTEGER sqlcode_
Definition: soci-odbc.h:323
database_product product_
Definition: soci-odbc.h:316
odbc_soci_error(SQLSMALLINT htype, SQLHANDLE hndl, std::string const &msg)
Definition: soci-odbc.h:326
bool is_odbc_error(SQLRETURN rc)
Definition: soci-odbc.h:399
std::vector< SQLLEN > indHolderVec_
Definition: soci-odbc.h:192
details::exchange_type type_
Definition: soci-odbc.h:126
odbc_vector_use_type_backend(odbc_statement_backend &st)
Definition: soci-odbc.h:166
odbc_session_backend & session_
Definition: soci-odbc.h:266
odbc_standard_type_backend_base(odbc_statement_backend &st)
Definition: soci-odbc.h:57
odbc_session_backend & session_
Definition: soci-odbc.h:231
#define SOCI_ODBC_DECL
Definition: soci-odbc.h:23
details::exchange_type type_
Definition: soci-odbc.h:158
std::vector< std::string > names_
Definition: soci-odbc.h:241
std::string interpret_odbc_error(SQLSMALLINT htype, SQLHANDLE hndl, std::string const &msg)
Definition: soci-odbc.h:346
SQLINTEGER native_error_code() const
Definition: soci-odbc.h:337
SOCI_ODBC_DECL odbc_backend_factory const odbc
SOCI_ODBC_DECL char const * odbc_option_driver_complete
std::string connection_string_
Definition: soci-odbc.h:315
virtual std::string get_backend_name() const
Definition: soci-odbc.h:284
std::vector< SQLLEN > indHolderVec_
Definition: soci-odbc.h:123
std::string get_connection_string() const
Definition: soci-odbc.h:310
SQLCHAR const * odbc_error_code() const
Definition: soci-odbc.h:333
odbc_statement_backend & statement_
Definition: soci-odbc.h:72
SOCI_ODBC_DECL backend_factory const * factory_odbc()
std::vector< ISM::CombinatorialTrainerParameters > parameters


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:41