backends/odbc/session.cpp
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 #define SOCI_ODBC_SOURCE
9 #include "soci-odbc.h"
10 #include "session.h"
11 
12 #include <cstdio>
13 
14 using namespace soci;
15 using namespace soci::details;
16 
17 char const * soci::odbc_option_driver_complete = "odbc.driver_complete";
18 
21  : henv_(0), hdbc_(0), product_(prod_uninitialized)
22 {
23  SQLRETURN rc;
24 
25  // Allocate environment handle
26  rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv_);
27  if (is_odbc_error(rc))
28  {
29  throw soci_error("Unable to get environment handle");
30  }
31 
32  // Set the ODBC version environment attribute
33  rc = SQLSetEnvAttr(henv_, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
34  if (is_odbc_error(rc))
35  {
36  throw odbc_soci_error(SQL_HANDLE_ENV, henv_,
37  "Setting ODBC version");
38  }
39 
40  // Allocate connection handle
41  rc = SQLAllocHandle(SQL_HANDLE_DBC, henv_, &hdbc_);
42  if (is_odbc_error(rc))
43  {
44  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
45  "Allocating connection handle");
46  }
47 
48  SQLCHAR outConnString[1024];
49  SQLSMALLINT strLength;
50 
51  // Prompt the user for any missing information (typically UID/PWD) in the
52  // connection string by default but allow overriding this using "prompt"
53  // option.
54  SQLHWND hwnd_for_prompt = NULL;
55  unsigned completion = SQL_DRIVER_COMPLETE;
56  std::string completionString;
57  if (parameters.get_option(odbc_option_driver_complete, completionString))
58  {
59  // The value of the option is supposed to be just the integer value of
60  // one of SQL_DRIVER_XXX constants but don't check for the exact value in
61  // case more of them are added in the future, the ODBC driver will return
62  // an error if we pass it an invalid value anyhow.
63  if (std::sscanf(completionString.c_str(), "%u", &completion) != 1)
64  {
65  throw soci_error("Invalid non-numeric driver completion option value \"" +
66  completionString + "\".");
67  }
68  }
69 
70 #ifdef _WIN32
71  if (completion != SQL_DRIVER_NOPROMPT)
72  hwnd_for_prompt = ::GetDesktopWindow();
73 #endif // _WIN32
74 
75  std::string const & connectString = parameters.get_connect_string();
76  rc = SQLDriverConnect(hdbc_, hwnd_for_prompt,
77  (SQLCHAR *)connectString.c_str(),
78  (SQLSMALLINT)connectString.size(),
79  outConnString, 1024, &strLength,
80  static_cast<SQLUSMALLINT>(completion));
81 
82  if (is_odbc_error(rc))
83  {
84  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
85  "Error Connecting to database");
86  }
87 
88  connection_string_.assign((const char*)outConnString, strLength);
89 
91 }
92 
94 {
95  clean_up();
96 }
97 
99 {
100  SQLRETURN rc = SQLSetConnectAttr( hdbc_, SQL_ATTR_AUTOCOMMIT,
101  (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 );
102  if (is_odbc_error(rc))
103  {
104  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
105  "Begin Transaction");
106  }
107 }
108 
110 {
111  SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_COMMIT);
112  if (is_odbc_error(rc))
113  {
114  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
115  "Committing");
116  }
118 }
119 
121 {
122  SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_ROLLBACK);
123  if (is_odbc_error(rc))
124  {
125  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
126  "Rolling back");
127  }
129 }
130 
132  session & s, std::string const & sequence, long & value)
133 {
134  std::string query;
135 
136  switch ( get_database_product() )
137  {
138  case prod_firebird:
139  query = "select next value for " + sequence + " from rdb$database";
140  break;
141 
142  case prod_oracle:
143  query = "select " + sequence + ".nextval from dual";
144  break;
145 
146  case prod_postgresql:
147  query = "select nextval('" + sequence + "')";
148  break;
149 
150  case prod_mssql:
151  case prod_mysql:
152  case prod_sqlite:
153  // These RDBMS implement get_last_insert_id() instead.
154  return false;
155 
156  case prod_unknown:
157  // For this one we can't do anything at all.
158  return false;
159 
160  case prod_uninitialized:
161  // This is not supposed to happen at all but still cover this case
162  // here to avoid gcc warnings about unhandled enum values in a
163  // switch.
164  return false;
165  }
166 
167  s << query, into(value);
168 
169  return true;
170 }
171 
173  session & s, std::string const & table, long & value)
174 {
175  std::string query;
176 
177  switch ( get_database_product() )
178  {
179  case prod_mssql:
180  query = "select ident_current('" + table + "')";
181  break;
182 
183  case prod_mysql:
184  query = "select last_insert_id()";
185  break;
186 
187  case prod_sqlite:
188  query = "select last_insert_rowid()";
189  break;
190 
191  case prod_firebird:
192  case prod_oracle:
193  case prod_postgresql:
194  // For these RDBMS get_next_sequence_value() should have been used.
195  return false;
196 
197 
198  case prod_unknown:
199  // For this one we can't do anything at all.
200  return false;
201 
202  case prod_uninitialized:
203  // As above, this is not supposed to happen but put it here to
204  // mollify gcc.
205  return false;
206  }
207 
208  s << query, into(value);
209 
210  return true;
211 }
212 
214 {
215  SQLRETURN rc = SQLSetConnectAttr( hdbc_, SQL_ATTR_AUTOCOMMIT,
216  (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 );
217  if (is_odbc_error(rc))
218  {
219  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
220  "Set Auto Commit");
221  }
222 }
223 
224 
226 {
227  SQLRETURN rc = SQLDisconnect(hdbc_);
228  if (is_odbc_error(rc))
229  {
230  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
231  "SQLDisconnect");
232  }
233 
234  rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc_);
235  if (is_odbc_error(rc))
236  {
237  throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
238  "SQLFreeHandle DBC");
239  }
240 
241  rc = SQLFreeHandle(SQL_HANDLE_ENV, henv_);
242  if (is_odbc_error(rc))
243  {
244  throw odbc_soci_error(SQL_HANDLE_ENV, henv_,
245  "SQLFreeHandle ENV");
246  }
247 }
248 
250 {
251  return new odbc_statement_backend(*this);
252 }
253 
255 {
256  return new odbc_rowid_backend(*this);
257 }
258 
260 {
261  return new odbc_blob_backend(*this);
262 }
263 
266 {
267  // Cache the product type, it's not going to change during our life time.
269  return product_;
270 
271  char product_name[1024];
272  SQLSMALLINT len = sizeof(product_name);
273  SQLRETURN rc = SQLGetInfo(hdbc_, SQL_DBMS_NAME, product_name, len, &len);
274  if (is_odbc_error(rc))
275  {
276  throw odbc_soci_error(SQL_HANDLE_DBC, henv_,
277  "SQLGetInfo(SQL_DBMS_NAME)");
278  }
279 
280  if (strcmp(product_name, "Firebird") == 0)
282  else if (strcmp(product_name, "Microsoft SQL Server") == 0)
284  else if (strcmp(product_name, "MySQL") == 0)
286  else if (strcmp(product_name, "Oracle") == 0)
288  else if (strcmp(product_name, "PostgreSQL") == 0)
290  else if (strcmp(product_name, "SQLite") == 0)
292  else
294 
295  return product_;
296 }
details::into_container< T, details::no_indicator > into(T &t)
Definition: into.h:51
virtual odbc_blob_backend * make_blob_backend()
database_product product_
Definition: soci-odbc.h:316
virtual odbc_statement_backend * make_statement_backend()
odbc_session_backend(connection_parameters const &parameters)
bool is_odbc_error(SQLRETURN rc)
Definition: soci-odbc.h:399
std::string const & get_connect_string() const
SOCI_ODBC_DECL char const * odbc_option_driver_complete
virtual odbc_rowid_backend * make_rowid_backend()
std::string connection_string_
Definition: soci-odbc.h:315
std::string connectString
Definition: test-db2.cpp:21
virtual bool get_next_sequence_value(session &s, std::string const &sequence, long &value)
virtual bool get_last_insert_id(session &s, std::string const &table, long &value)
std::vector< ISM::CombinatorialTrainerParameters > parameters
bool get_option(const char *name, std::string &value) const


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