fastcgi++
|
00001 00002 /*************************************************************************** 00003 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] * 00004 * * 00005 * This file is part of fastcgi++. * 00006 * * 00007 * fastcgi++ is free software: you can redistribute it and/or modify it * 00008 * under the terms of the GNU Lesser General Public License as published * 00009 * by the Free Software Foundation, either version 3 of the License, or (at * 00010 * your option) any later version. * 00011 * * 00012 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT * 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 00015 * License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License * 00018 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. * 00019 ****************************************************************************/ 00020 00021 00022 #ifndef MYSQL_HPP 00023 #define MYSQL_HPP 00024 00025 #include <mysql/mysql.h> 00026 #include <boost/scoped_array.hpp> 00027 #include <boost/scoped_ptr.hpp> 00028 #include <deque> 00029 00030 #include <asql/asql.hpp> 00031 00033 namespace ASql 00034 { 00036 namespace MySQL 00037 { 00038 class Statement; 00039 00041 class Connection: public ConnectionPar<MySQL::Statement> 00042 { 00043 private: 00046 00047 boost::scoped_array<MYSQL> m_connection; 00048 00051 00052 boost::scoped_array<MYSQL_STMT*> foundRowsStatement; 00053 00056 00057 boost::scoped_array<MYSQL_BIND> foundRowsBinding; 00058 00059 bool m_initialized; 00060 00061 public: 00076 Connection(const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag, const char* const charset="latin1", const int threads_=1): ConnectionPar<MySQL::Statement>(threads_), m_initialized(false) 00077 { 00078 connect(host, user, passwd, db, port, unix_socket, client_flag, charset); 00079 } 00080 00083 00087 Connection(const int threads_=1): 00088 ConnectionPar<MySQL::Statement>(threads_), 00089 m_connection(new MYSQL[threads_]), 00090 foundRowsStatement(new MYSQL_STMT*[threads_]), 00091 foundRowsBinding(new MYSQL_BIND[threads_]), 00092 m_initialized(false) {} 00093 ~Connection(); 00094 00097 00107 void connect(const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag, const char* const charset="latin1"); 00108 00111 00114 void getFoundRows(unsigned long long* const& rows, const unsigned int id); 00115 00116 MYSQL& connection(unsigned int id) { return m_connection[id]; } 00117 00118 inline void commit(const unsigned int thread=0) { mysql_commit(&m_connection[thread]); } 00119 inline void rollback(const unsigned int thread=0) { mysql_rollback(&m_connection[thread]); } 00120 }; 00121 00123 00128 class Statement: public ASql::Statement 00129 { 00130 public: 00132 00156 Statement(Connection& connection_, const char* const queryString, const size_t queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet): 00157 ASql::Statement(connection_.threads()), 00158 connection(connection_), 00159 stmt(new MYSQL_STMT*[connection_.threads()]), 00160 m_initialized(false), 00161 paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]), 00162 resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]), 00163 m_stop(new const bool*[connection_.threads()]) 00164 { 00165 init(queryString, queryLength, parameterSet, resultSet); 00166 } 00167 00169 00172 Statement(Connection& connection_): 00173 ASql::Statement(connection_.threads()), 00174 connection(connection_), 00175 stmt(new MYSQL_STMT*[connection_.threads()]), 00176 m_initialized(false), 00177 paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]), 00178 resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]), 00179 m_stop(new const bool*[connection_.threads()]) {} 00180 00181 ~Statement(); 00182 00184 00208 void init(const char* const& queryString, const size_t& queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet, bool customPlaceholders=false); 00209 00211 00235 void execute(const Data::Set* const parameters, Data::SetContainer* const results, unsigned long long int* const insertId=0, unsigned long long int* const rows=0, bool docommit=true, const unsigned int thread=0); 00236 00238 00257 bool execute(const Data::Set* const parameters, Data::Set& results, bool docommit=true, const unsigned int thread=0); 00258 00260 00275 void execute(const Data::SetContainer& parameters, unsigned long long int* rows=0, bool docommit=true, const unsigned int thread=0); 00276 00278 00291 inline void queue(QueryPar& query, int instance=-1) 00292 { 00293 connection.queue(this, query, instance); 00294 } 00295 private: 00296 Connection& connection; 00297 00299 boost::scoped_array<MYSQL_STMT*> stmt; 00300 00302 std::deque<unsigned char> paramOrder; 00303 00305 boost::scoped_array<boost::scoped_array<MYSQL_BIND> > paramsBindings; 00306 00308 boost::scoped_array<boost::scoped_array<MYSQL_BIND> > resultsBindings; 00309 00311 00332 static void buildBindings(MYSQL_STMT* const& stmt, const Data::Set& set, Data::Conversions& conversions, boost::scoped_array<MYSQL_BIND>& bindings, const std::deque<unsigned char>* order=0); 00333 00335 00349 static void bindBindings(Data::Set& set, Data::Conversions& conversions, boost::scoped_array<MYSQL_BIND>& bindings, const std::deque<unsigned char>* order=0); 00350 00352 00355 void executeParameters(const Data::Set* const& parameters, const unsigned int thread); 00356 00358 00363 bool executeResult(Data::Set& row, const unsigned int thread); 00364 00365 bool m_initialized; 00366 00367 boost::scoped_array<const bool*> m_stop; 00368 00369 friend class ConnectionPar<Statement>; 00370 friend class Transaction<Statement>; 00371 }; 00372 00373 typedef ASql::Transaction<Statement> Transaction; 00374 00376 00381 template<class T> struct TypedConversion: public Data::Conversion 00382 { 00384 enum_field_types bufferType; 00385 00387 unsigned long length; 00388 00390 virtual void convertResult() { grabIt(*(T*)external); } 00391 00393 virtual void convertParam(); 00394 00396 00399 void* getPointer() { return 0; } 00400 00407 TypedConversion(const int& column_, MYSQL_STMT* const& statement_, const enum_field_types& bufferType_, void*& buffer_): bufferType(bufferType_), length(0), buffer(buffer_), column(column_), statement(statement_) {} 00408 protected: 00410 void*& buffer; 00411 00413 int column; 00414 00416 MYSQL_STMT* const& statement; 00417 00419 00422 void grabIt(T& data); 00423 }; 00424 00426 template<> struct TypedConversion<Data::Datetime>: public Data::Conversion 00427 { 00429 MYSQL_TIME internal; 00430 00432 virtual void convertResult(); 00433 00435 virtual void convertParam(); 00436 00438 00441 void* getPointer() { return &internal; } 00442 }; 00443 00445 template<> struct TypedConversion<Data::Date>: public TypedConversion<Data::Datetime> 00446 { 00448 void convertResult(); 00449 00451 void convertParam(); 00452 }; 00453 00455 template<> struct TypedConversion<Data::Time>: public TypedConversion<Data::Datetime> 00456 { 00458 void convertResult(); 00459 00461 void convertParam(); 00462 }; 00463 00465 template<> struct TypedConversion<Data::Wtext>: public TypedConversion<Data::Blob> 00466 { 00472 TypedConversion(int column_, MYSQL_STMT* const& statement_, void*& buffer_): TypedConversion<Data::Blob>(column_, statement_, MYSQL_TYPE_STRING, buffer_) {} 00473 00475 void convertResult(); 00476 00478 void convertParam(); 00479 private: 00481 std::vector<char> inputBuffer; 00482 }; 00483 00485 struct Error: public ASql::Error 00486 { 00487 Error(MYSQL* mysql); 00488 Error(MYSQL_STMT* stmt); 00489 }; 00490 00491 extern const char CodeConversionErrorMsg[]; 00492 } 00493 } 00494 00495 #endif