SOCI Logo Get SOCI at SourceForge.net. Fast, secure and Free Open Source software downloads

session.cpp

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
SourceForge Logo

Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1