fastcgi++
mysql.hpp
Go to the documentation of this file.
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