backends/mysql/session.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
3 // MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #define SOCI_MYSQL_SOURCE
10 #include "soci-mysql.h"
11 #include <connection-parameters.h>
12 // std
13 #include <cctype>
14 #include <cerrno>
15 #include <ciso646>
16 #include <climits>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string>
20 
21 #ifdef _MSC_VER
22 #pragma warning(disable:4355)
23 #endif
24 
25 using namespace soci;
26 using namespace soci::details;
27 using std::string;
28 
29 
30 namespace
31 { // anonymous
32 
33 void skip_white(std::string::const_iterator *i,
34  std::string::const_iterator const & end, bool endok)
35 {
36  for (;;)
37  {
38  if (*i == end)
39  {
40  if (endok)
41  {
42  return;
43  }
44  else
45  {
46  throw soci_error("Unexpected end of connection string.");
47  }
48  }
49  if (std::isspace(**i))
50  {
51  ++*i;
52  }
53  else
54  {
55  return;
56  }
57  }
58 }
59 
60 std::string param_name(std::string::const_iterator *i,
61  std::string::const_iterator const & end)
62 {
63  std::string val("");
64  for (;;)
65  {
66  if (*i == end or (not std::isalpha(**i) and **i != '_'))
67  {
68  break;
69  }
70  val += **i;
71  ++*i;
72  }
73  return val;
74 }
75 
76 string param_value(string::const_iterator *i,
77  string::const_iterator const & end)
78 {
79  string err = "Malformed connection string.";
80  bool quot;
81  if (**i == '\'')
82  {
83  quot = true;
84  ++*i;
85  }
86  else
87  {
88  quot = false;
89  }
90  string val("");
91  for (;;)
92  {
93  if (*i == end)
94  {
95  if (quot)
96  {
97  throw soci_error(err);
98  }
99  else
100  {
101  break;
102  }
103  }
104  if (**i == '\'')
105  {
106  if (quot)
107  {
108  ++*i;
109  break;
110  }
111  else
112  {
113  throw soci_error(err);
114  }
115  }
116  if (not quot and std::isspace(**i))
117  {
118  break;
119  }
120  if (**i == '\\')
121  {
122  ++*i;
123  if (*i == end)
124  {
125  throw soci_error(err);
126  }
127  }
128  val += **i;
129  ++*i;
130  }
131  return val;
132 }
133 
134 bool valid_int(const string & s)
135 {
136  char *tail;
137  const char *cstr = s.c_str();
138  errno = 0;
139  long n = std::strtol(cstr, &tail, 10);
140  if (errno != 0 or n > INT_MAX or n < INT_MIN)
141  {
142  return false;
143  }
144  if (*tail != '\0')
145  {
146  return false;
147  }
148  return true;
149 }
150 
151 void parse_connect_string(const string & connectString,
152  string *host, bool *host_p,
153  string *user, bool *user_p,
154  string *password, bool *password_p,
155  string *db, bool *db_p,
156  string *unix_socket, bool *unix_socket_p,
157  int *port, bool *port_p, string *ssl_ca, bool *ssl_ca_p,
158  string *ssl_cert, bool *ssl_cert_p, string *ssl_key, bool *ssl_key_p,
159  int *local_infile, bool *local_infile_p,
160  string *charset, bool *charset_p)
161 {
162  *host_p = false;
163  *user_p = false;
164  *password_p = false;
165  *db_p = false;
166  *unix_socket_p = false;
167  *port_p = false;
168  *ssl_ca_p = false;
169  *ssl_cert_p = false;
170  *ssl_key_p = false;
171  *local_infile_p = false;
172  *charset_p = false;
173  string err = "Malformed connection string.";
174  string::const_iterator i = connectString.begin(),
175  end = connectString.end();
176  while (i != end)
177  {
178  skip_white(&i, end, true);
179  if (i == end)
180  {
181  return;
182  }
183  string par = param_name(&i, end);
184  skip_white(&i, end, false);
185  if (*i == '=')
186  {
187  ++i;
188  }
189  else
190  {
191  throw soci_error(err);
192  }
193  skip_white(&i, end, false);
194  string val = param_value(&i, end);
195  if (par == "port" and not *port_p)
196  {
197  if (not valid_int(val))
198  {
199  throw soci_error(err);
200  }
201  *port = std::atoi(val.c_str());
202  if (*port < 0)
203  {
204  throw soci_error(err);
205  }
206  *port_p = true;
207  }
208  else if (par == "host" and not *host_p)
209  {
210  *host = val;
211  *host_p = true;
212  }
213  else if (par == "user" and not *user_p)
214  {
215  *user = val;
216  *user_p = true;
217  }
218  else if ((par == "pass" or par == "password") and not *password_p)
219  {
220  *password = val;
221  *password_p = true;
222  }
223  else if ((par == "db" or par == "dbname" or par == "service") and
224  not *db_p)
225  {
226  *db = val;
227  *db_p = true;
228  }
229  else if (par == "unix_socket" and not *unix_socket_p)
230  {
231  *unix_socket = val;
232  *unix_socket_p = true;
233  }
234  else if (par == "sslca" and not *ssl_ca_p)
235  {
236  *ssl_ca = val;
237  *ssl_ca_p = true;
238  }
239  else if (par == "sslcert" and not *ssl_cert_p)
240  {
241  *ssl_cert = val;
242  *ssl_cert_p = true;
243  }
244  else if (par == "sslkey" and not *ssl_key_p)
245  {
246  *ssl_key = val;
247  *ssl_key_p = true;
248  }
249  else if (par == "local_infile" and not *local_infile_p)
250  {
251  if (not valid_int(val))
252  {
253  throw soci_error(err);
254  }
255  *local_infile = std::atoi(val.c_str());
256  if (*local_infile != 0 and *local_infile != 1)
257  {
258  throw soci_error(err);
259  }
260  *local_infile_p = true;
261  } else if (par == "charset" and not *charset_p)
262  {
263  *charset = val;
264  *charset_p = true;
265  }
266  else
267  {
268  throw soci_error(err);
269  }
270  }
271 }
272 
273 } // namespace anonymous
274 
277 {
278  string host, user, password, db, unix_socket, ssl_ca, ssl_cert, ssl_key,
279  charset;
280  int port, local_infile;
281  bool host_p, user_p, password_p, db_p, unix_socket_p, port_p,
282  ssl_ca_p, ssl_cert_p, ssl_key_p, local_infile_p, charset_p;
283  parse_connect_string(parameters.get_connect_string(), &host, &host_p, &user, &user_p,
284  &password, &password_p, &db, &db_p,
285  &unix_socket, &unix_socket_p, &port, &port_p,
286  &ssl_ca, &ssl_ca_p, &ssl_cert, &ssl_cert_p, &ssl_key, &ssl_key_p,
287  &local_infile, &local_infile_p, &charset, &charset_p);
288  conn_ = mysql_init(NULL);
289  if (conn_ == NULL)
290  {
291  throw soci_error("mysql_init() failed.");
292  }
293  if (charset_p)
294  {
295  if (0 != mysql_options(conn_, MYSQL_SET_CHARSET_NAME, charset.c_str()))
296  {
297  clean_up();
298  throw soci_error("mysql_options(MYSQL_SET_CHARSET_NAME) failed.");
299  }
300  }
301  if (ssl_ca_p)
302  {
303  mysql_ssl_set(conn_, ssl_key_p ? ssl_key.c_str() : NULL,
304  ssl_cert_p ? ssl_cert.c_str() : NULL,
305  ssl_ca_p ? ssl_ca.c_str() : NULL, 0, 0);
306  }
307  if (local_infile_p and local_infile == 1)
308  {
309  if (0 != mysql_options(conn_, MYSQL_OPT_LOCAL_INFILE, NULL))
310  {
311  clean_up();
312  throw soci_error(
313  "mysql_options() failed when trying to set local-infile.");
314  }
315  }
316  if (mysql_real_connect(conn_,
317  host_p ? host.c_str() : NULL,
318  user_p ? user.c_str() : NULL,
319  password_p ? password.c_str() : NULL,
320  db_p ? db.c_str() : NULL,
321  port_p ? port : 0,
322  unix_socket_p ? unix_socket.c_str() : NULL,
323 #ifdef CLIENT_MULTI_RESULTS
324  CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS) == NULL)
325 #else
326  CLIENT_FOUND_ROWS) == NULL)
327 #endif
328  {
329  string errMsg = mysql_error(conn_);
330  unsigned int errNum = mysql_errno(conn_);
331  clean_up();
332  throw mysql_soci_error(errMsg, errNum);
333  }
334 }
335 
337 {
338  clean_up();
339 }
340 
341 namespace // unnamed
342 {
343 
344 // helper function for hardcoded queries
345 void hard_exec(MYSQL *conn, const string & query)
346 {
347  if (0 != mysql_real_query(conn, query.c_str(),
348  static_cast<unsigned long>(query.size())))
349  {
350  throw soci_error(mysql_error(conn));
351  }
352 }
353 
354 } // namespace unnamed
355 
357 {
358  hard_exec(conn_, "BEGIN");
359 }
360 
362 {
363  hard_exec(conn_, "COMMIT");
364 }
365 
367 {
368  hard_exec(conn_, "ROLLBACK");
369 }
370 
372 {
373  if (conn_ != NULL)
374  {
375  mysql_close(conn_);
376  conn_ = NULL;
377  }
378 }
379 
381 {
382  return new mysql_statement_backend(*this);
383 }
384 
386 {
387  return new mysql_rowid_backend(*this);
388 }
389 
391 {
392  return new mysql_blob_backend(*this);
393 }
virtual mysql_statement_backend * make_statement_backend()
virtual mysql_rowid_backend * make_rowid_backend()
std::string const & get_connect_string() const
virtual mysql_blob_backend * make_blob_backend()
std::string connectString
Definition: test-db2.cpp:21
std::vector< ISM::CombinatorialTrainerParameters > parameters
mysql_session_backend(connection_parameters const &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