00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00029 #include <asql/asql.hpp>
00030
00032 namespace ASql
00033 {
00035 namespace MySQL
00036 {
00037 class Statement;
00038
00042 class Connection: public ConnectionPar<MySQL::Statement>
00043 {
00044 private:
00048 boost::scoped_array<MYSQL> m_connection;
00049
00053 boost::scoped_array<MYSQL_STMT*> foundRowsStatement;
00054
00058 boost::scoped_array<MYSQL_BIND> foundRowsBinding;
00059
00060 bool m_initialized;
00061
00062 public:
00077 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)
00078 {
00079 connect(host, user, passwd, db, port, unix_socket, client_flag, charset);
00080 }
00081
00088 Connection(const int threads_=1):
00089 ConnectionPar<MySQL::Statement>(threads_),
00090 m_connection(new MYSQL[threads_]),
00091 foundRowsStatement(new MYSQL_STMT*[threads_]),
00092 foundRowsBinding(new MYSQL_BIND[threads_]),
00093 m_initialized(false) {}
00094 ~Connection();
00095
00108 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");
00109
00115 void getFoundRows(unsigned long long* const& rows, const unsigned int id);
00116
00117 MYSQL& connection(unsigned int id) { return m_connection[id]; }
00118
00119 inline void commit(const unsigned int thread=0) { mysql_commit(&m_connection[thread]); }
00120 inline void rollback(const unsigned int thread=0) { mysql_rollback(&m_connection[thread]); }
00121 };
00122
00129 class Statement: public ASql::Statement
00130 {
00131 public:
00152 Statement(Connection& connection_, const char* const queryString, const size_t queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet):
00153 ASql::Statement(connection_.threads()),
00154 connection(connection_),
00155 stmt(new MYSQL_STMT*[connection_.threads()]),
00156 m_initialized(false),
00157 paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
00158 resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
00159 m_stop(new const bool*[connection_.threads()])
00160 {
00161 init(queryString, queryLength, parameterSet, resultSet);
00162 }
00168 Statement(Connection& connection_):
00169 ASql::Statement(connection_.threads()),
00170 connection(connection_),
00171 stmt(new MYSQL_STMT*[connection_.threads()]),
00172 m_initialized(false),
00173 paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
00174 resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
00175 m_stop(new const bool*[connection_.threads()]) {}
00176
00177 ~Statement();
00178
00198 void init(const char* const& queryString, const size_t& queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet);
00199
00220 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);
00221
00240 bool execute(const Data::Set* const parameters, Data::Set& results, bool docommit=true, const unsigned int thread=0);
00241
00257 void execute(const Data::SetContainer& parameters, unsigned long long int* rows=0, bool docommit=true, const unsigned int thread=0);
00258
00272 inline void queue(Query& query)
00273 {
00274 connection.queue(this, query);
00275 }
00276 private:
00277 Connection& connection;
00278
00282 boost::scoped_array<MYSQL_STMT*> stmt;
00283
00287 boost::scoped_array<boost::scoped_array<MYSQL_BIND> > paramsBindings;
00288
00292 boost::scoped_array<boost::scoped_array<MYSQL_BIND> > resultsBindings;
00293
00312 static void buildBindings(MYSQL_STMT* const& stmt, const Data::Set& set, Data::Conversions& conversions, boost::scoped_array<MYSQL_BIND>& bindings);
00313
00328 static void bindBindings(Data::Set& set, Data::Conversions& conversions, boost::scoped_array<MYSQL_BIND>& bindings);
00329
00335 void executeParameters(const Data::Set* const& parameters, const unsigned int thread);
00336
00344 bool executeResult(Data::Set& row, const unsigned int thread);
00345
00346 bool m_initialized;
00347
00348 boost::scoped_array<const bool*> m_stop;
00349
00350 friend class ConnectionPar<Statement>;
00351 friend class Transaction<Statement>;
00352 };
00353
00354 typedef ASql::Transaction<Statement> Transaction;
00355
00362 template<class T> struct TypedConversion: public Data::Conversion
00363 {
00367 enum_field_types bufferType;
00368
00372 unsigned long length;
00373
00377 virtual void convertResult() { grabIt(*(T*)external); }
00378
00382 virtual void convertParam();
00383
00390 void* getPointer() { return 0; }
00391
00398 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_) {}
00399 protected:
00403 void*& buffer;
00404
00408 int column;
00409
00413 MYSQL_STMT* const& statement;
00414
00420 void grabIt(T& data);
00421 };
00422
00426 template<> struct TypedConversion<Data::Datetime>: public Data::Conversion
00427 {
00431 MYSQL_TIME internal;
00435 virtual void convertResult();
00439 virtual void convertParam();
00445 void* getPointer() { return &internal; }
00446 };
00447
00451 template<> struct TypedConversion<Data::Date>: public TypedConversion<Data::Datetime>
00452 {
00456 void convertResult();
00460 void convertParam();
00461 };
00462
00466 template<> struct TypedConversion<Data::Time>: public TypedConversion<Data::Datetime>
00467 {
00471 void convertResult();
00475 void convertParam();
00476 };
00477
00481 template<> struct TypedConversion<Data::Wtext>: public TypedConversion<Data::Blob>
00482 {
00488 TypedConversion(int column_, MYSQL_STMT* const& statement_, void*& buffer_): TypedConversion<Data::Blob>(column_, statement_, MYSQL_TYPE_STRING, buffer_) {}
00492 void convertResult();
00496 void convertParam();
00497 private:
00501 std::vector<char> inputBuffer;
00502 };
00503
00507 struct Error: public ASql::Error
00508 {
00509 Error(MYSQL* mysql);
00510 Error(MYSQL_STMT* stmt);
00511 };
00512
00513 extern const char CodeConversionErrorMsg[];
00514 }
00515 }
00516
00517 #endif