00001 // 00002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton 00003 // MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski 00004 // Distributed under the Boost Software License, Version 1.0. 00005 // (See accompanying file LICENSE_1_0.txt or copy at 00006 // http://www.boost.org/LICENSE_1_0.txt) 00007 // 00008 00009 #define SOCI_MYSQL_SOURCE 00010 #include "soci-mysql.h" 00011 // std 00012 #include <cctype> 00013 #include <cerrno> 00014 #include <ciso646> 00015 #include <climits> 00016 #include <cstdio> 00017 #include <cstdlib> 00018 #include <string> 00019 00020 #ifdef _MSC_VER 00021 #pragma warning(disable:4355) 00022 #endif 00023 00024 using namespace soci; 00025 using namespace soci::details; 00026 00027 00028 namespace 00029 { // anonymous 00030 00031 void skip_white(std::string::const_iterator *i, 00032 std::string::const_iterator const & end, bool endok) 00033 { 00034 for (;;) 00035 { 00036 if (*i == end) 00037 { 00038 if (endok) 00039 { 00040 return; 00041 } 00042 else 00043 { 00044 throw soci_error("Unexpected end of connection string."); 00045 } 00046 } 00047 if (std::isspace(**i)) 00048 { 00049 ++*i; 00050 } 00051 else 00052 { 00053 return; 00054 } 00055 } 00056 } 00057 00058 std::string param_name(std::string::const_iterator *i, 00059 std::string::const_iterator const & end) 00060 { 00061 std::string val(""); 00062 for (;;) 00063 { 00064 if (*i == end or (not std::isalpha(**i) and **i != '_')) 00065 { 00066 break; 00067 } 00068 val += **i; 00069 ++*i; 00070 } 00071 return val; 00072 } 00073 00074 std::string param_value(std::string::const_iterator *i, 00075 std::string::const_iterator const & end) 00076 { 00077 std::string err = "Malformed connection string."; 00078 bool quot; 00079 if (**i == '\'') 00080 { 00081 quot = true; 00082 ++*i; 00083 } 00084 else 00085 { 00086 quot = false; 00087 } 00088 std::string val(""); 00089 for (;;) 00090 { 00091 if (*i == end) 00092 { 00093 if (quot) 00094 { 00095 throw soci_error(err); 00096 } 00097 else 00098 { 00099 break; 00100 } 00101 } 00102 if (**i == '\'') 00103 { 00104 if (quot) 00105 { 00106 ++*i; 00107 break; 00108 } 00109 else 00110 { 00111 throw soci_error(err); 00112 } 00113 } 00114 if (not quot and std::isspace(**i)) 00115 { 00116 break; 00117 } 00118 if (**i == '\\') 00119 { 00120 ++*i; 00121 if (*i == end) 00122 { 00123 throw soci_error(err); 00124 } 00125 } 00126 val += **i; 00127 ++*i; 00128 } 00129 return val; 00130 } 00131 00132 bool valid_int(const std::string & s) 00133 { 00134 char *tail; 00135 const char *cstr = s.c_str(); 00136 errno = 0; 00137 long n = std::strtol(cstr, &tail, 10); 00138 if (errno != 0 or n > INT_MAX or n < INT_MIN) 00139 { 00140 return false; 00141 } 00142 if (*tail != '\0') 00143 { 00144 return false; 00145 } 00146 return true; 00147 } 00148 00149 void parse_connect_string(const std::string & connectString, 00150 std::string *host, bool *host_p, 00151 std::string *user, bool *user_p, 00152 std::string *password, bool *password_p, 00153 std::string *db, bool *db_p, 00154 std::string *unix_socket, bool *unix_socket_p, 00155 int *port, bool *port_p) 00156 { 00157 *host_p = false; 00158 *user_p = false; 00159 *password_p = false; 00160 *db_p = false; 00161 *unix_socket_p = false; 00162 *port_p = false; 00163 std::string err = "Malformed connection string."; 00164 std::string::const_iterator i = connectString.begin(), 00165 end = connectString.end(); 00166 while (i != end) 00167 { 00168 skip_white(&i, end, true); 00169 if (i == end) 00170 { 00171 return; 00172 } 00173 std::string par = param_name(&i, end); 00174 skip_white(&i, end, false); 00175 if (*i == '=') 00176 { 00177 ++i; 00178 } 00179 else 00180 { 00181 throw soci_error(err); 00182 } 00183 skip_white(&i, end, false); 00184 std::string val = param_value(&i, end); 00185 if (par == "port" and not *port_p) 00186 { 00187 if (not valid_int(val)) 00188 { 00189 throw soci_error(err); 00190 } 00191 *port = std::atoi(val.c_str()); 00192 if (port < 0) 00193 { 00194 throw soci_error(err); 00195 } 00196 *port_p = true; 00197 } 00198 else if (par == "host" and not *host_p) 00199 { 00200 *host = val; 00201 *host_p = true; 00202 } 00203 else if (par == "user" and not *user_p) 00204 { 00205 *user = val; 00206 *user_p = true; 00207 } 00208 else if ((par == "pass" or par == "password") and not *password_p) 00209 { 00210 *password = val; 00211 *password_p = true; 00212 } 00213 else if ((par == "db" or par == "dbname") and not *db_p) 00214 { 00215 *db = val; 00216 *db_p = true; 00217 } 00218 else if (par == "unix_socket" and not *unix_socket_p) 00219 { 00220 *unix_socket = val; 00221 *unix_socket_p = true; 00222 } 00223 else 00224 { 00225 throw soci_error(err); 00226 } 00227 } 00228 } 00229 00230 } // namespace anonymous 00231 00232 mysql_session_backend::mysql_session_backend( 00233 std::string const & connectString) 00234 { 00235 std::string host, user, password, db, unix_socket; 00236 int port; 00237 bool host_p, user_p, password_p, db_p, unix_socket_p, port_p; 00238 parse_connect_string(connectString, &host, &host_p, &user, &user_p, 00239 &password, &password_p, &db, &db_p, 00240 &unix_socket, &unix_socket_p, &port, &port_p); 00241 conn_ = mysql_init(NULL); 00242 if (conn_ == NULL) 00243 { 00244 throw soci_error("mysql_init() failed."); 00245 } 00246 if (mysql_real_connect(conn_, 00247 host_p ? host.c_str() : NULL, 00248 user_p ? user.c_str() : NULL, 00249 password_p ? password.c_str() : NULL, 00250 db_p ? db.c_str() : NULL, 00251 port_p ? port : 0, 00252 unix_socket_p ? unix_socket.c_str() : NULL, 00253 0) == NULL) 00254 { 00255 std::string errMsg = mysql_error(conn_); 00256 unsigned int errNum = mysql_errno(conn_); 00257 clean_up(); 00258 throw mysql_soci_error(errMsg, errNum); 00259 } 00260 } 00261 00262 mysql_session_backend::~mysql_session_backend() 00263 { 00264 clean_up(); 00265 } 00266 00267 namespace // unnamed 00268 { 00269 00270 // helper function for hardcoded queries 00271 void hard_exec(MYSQL *conn, const std::string & query) 00272 { 00273 if (0 != mysql_real_query(conn, query.c_str(), 00274 static_cast<unsigned long>(query.size()))) 00275 { 00276 throw soci_error(mysql_error(conn)); 00277 } 00278 } 00279 00280 } // namespace unnamed 00281 00282 void mysql_session_backend::begin() 00283 { 00284 hard_exec(conn_, "BEGIN"); 00285 } 00286 00287 void mysql_session_backend::commit() 00288 { 00289 hard_exec(conn_, "COMMIT"); 00290 } 00291 00292 void mysql_session_backend::rollback() 00293 { 00294 hard_exec(conn_, "ROLLBACK"); 00295 } 00296 00297 void mysql_session_backend::clean_up() 00298 { 00299 if (conn_ != NULL) 00300 { 00301 mysql_close(conn_); 00302 conn_ = NULL; 00303 } 00304 } 00305 00306 mysql_statement_backend * mysql_session_backend::make_statement_backend() 00307 { 00308 return new mysql_statement_backend(*this); 00309 } 00310 00311 mysql_rowid_backend * mysql_session_backend::make_rowid_backend() 00312 { 00313 return new mysql_rowid_backend(*this); 00314 } 00315 00316 mysql_blob_backend * mysql_session_backend::make_blob_backend() 00317 { 00318 return new mysql_blob_backend(*this); 00319 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1