fastcgi++
mysql.hpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] *
4 * *
5 * This file is part of fastcgi++. *
6 * *
7 * fastcgi++ is free software: you can redistribute it and/or modify it *
8 * under the terms of the GNU Lesser General Public License as published *
9 * by the Free Software Foundation, either version 3 of the License, or (at *
10 * your option) any later version. *
11 * *
12 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT *
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public *
15 * License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public License *
18 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
19 ****************************************************************************/
20 
21 
22 #ifndef MYSQL_HPP
23 #define MYSQL_HPP
24 
25 #include <mysql/mysql.h>
26 #include <boost/scoped_array.hpp>
27 #include <boost/scoped_ptr.hpp>
28 #include <deque>
29 
30 #include <asql/asql.hpp>
31 
33 namespace ASql
34 {
36  namespace MySQL
37  {
38  class Statement;
39 
41  class Connection: public ConnectionPar<MySQL::Statement>
42  {
43  private:
46 
47  boost::scoped_array<MYSQL> m_connection;
48 
51 
52  boost::scoped_array<MYSQL_STMT*> foundRowsStatement;
53 
56 
57  boost::scoped_array<MYSQL_BIND> foundRowsBinding;
58 
60 
61  public:
76  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)
77  {
78  connect(host, user, passwd, db, port, unix_socket, client_flag, charset);
79  }
80 
83 
87  Connection(const int threads_=1):
88  ConnectionPar<MySQL::Statement>(threads_),
89  m_connection(new MYSQL[threads_]),
90  foundRowsStatement(new MYSQL_STMT*[threads_]),
91  foundRowsBinding(new MYSQL_BIND[threads_]),
92  m_initialized(false) {}
93  ~Connection();
94 
97 
107  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");
108 
111 
114  void getFoundRows(unsigned long long* const& rows, const unsigned int id);
115 
116  MYSQL& connection(unsigned int id) { return m_connection[id]; }
117 
118  inline void commit(const unsigned int thread=0) { mysql_commit(&m_connection[thread]); }
119  inline void rollback(const unsigned int thread=0) { mysql_rollback(&m_connection[thread]); }
120  };
121 
123 
129  {
130  public:
132 
156  Statement(Connection& connection_, const char* const queryString, const size_t queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet):
157  ASql::Statement(connection_.threads()),
158  connection(connection_),
159  stmt(new MYSQL_STMT*[connection_.threads()]),
160  m_initialized(false),
161  paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
162  resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
163  m_stop(new const bool*[connection_.threads()])
164  {
165  init(queryString, queryLength, parameterSet, resultSet);
166  }
167 
169 
172  Statement(Connection& connection_):
173  ASql::Statement(connection_.threads()),
174  connection(connection_),
175  stmt(new MYSQL_STMT*[connection_.threads()]),
176  m_initialized(false),
177  paramsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
178  resultsBindings(new boost::scoped_array<MYSQL_BIND>[connection_.threads()]),
179  m_stop(new const bool*[connection_.threads()]) {}
180 
181  ~Statement();
182 
184 
208  void init(const char* const& queryString, const size_t& queryLength, const Data::Set* const parameterSet, const Data::Set* const resultSet, bool customPlaceholders=false);
209 
211 
235  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);
236 
238 
257  bool execute(const Data::Set* const parameters, Data::Set& results, bool docommit=true, const unsigned int thread=0);
258 
260 
275  void execute(const Data::SetContainer& parameters, unsigned long long int* rows=0, bool docommit=true, const unsigned int thread=0);
276 
278 
291  inline void queue(QueryPar& query, int instance=-1)
292  {
293  connection.queue(this, query, instance);
294  }
295  private:
297 
299  boost::scoped_array<MYSQL_STMT*> stmt;
300 
302  std::deque<unsigned char> paramOrder;
303 
305  boost::scoped_array<boost::scoped_array<MYSQL_BIND> > paramsBindings;
306 
308  boost::scoped_array<boost::scoped_array<MYSQL_BIND> > resultsBindings;
309 
311 
332  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);
333 
335 
349  static void bindBindings(Data::Set& set, Data::Conversions& conversions, boost::scoped_array<MYSQL_BIND>& bindings, const std::deque<unsigned char>* order=0);
350 
352 
355  void executeParameters(const Data::Set* const& parameters, const unsigned int thread);
356 
358 
363  bool executeResult(Data::Set& row, const unsigned int thread);
364 
366 
367  boost::scoped_array<const bool*> m_stop;
368 
369  friend class ConnectionPar<Statement>;
370  friend class Transaction<Statement>;
371  };
372 
374 
376 
381  template<class T> struct TypedConversion: public Data::Conversion
382  {
384  enum_field_types bufferType;
385 
387  unsigned long length;
388 
390  virtual void convertResult() { grabIt(*(T*)external); }
391 
393  virtual void convertParam();
394 
396 
399  void* getPointer() { return 0; }
400 
407  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_) {}
408  protected:
410  void*& buffer;
411 
413  int column;
414 
416  MYSQL_STMT* const& statement;
417 
419 
422  void grabIt(T& data);
423  };
424 
426  template<> struct TypedConversion<Data::Datetime>: public Data::Conversion
427  {
429  MYSQL_TIME internal;
430 
432  virtual void convertResult();
433 
435  virtual void convertParam();
436 
438 
441  void* getPointer() { return &internal; }
442  };
443 
445  template<> struct TypedConversion<Data::Date>: public TypedConversion<Data::Datetime>
446  {
448  void convertResult();
449 
451  void convertParam();
452  };
453 
455  template<> struct TypedConversion<Data::Time>: public TypedConversion<Data::Datetime>
456  {
458  void convertResult();
459 
461  void convertParam();
462  };
463 
465  template<> struct TypedConversion<Data::Wtext>: public TypedConversion<Data::Blob>
466  {
472  TypedConversion(int column_, MYSQL_STMT* const& statement_, void*& buffer_): TypedConversion<Data::Blob>(column_, statement_, MYSQL_TYPE_STRING, buffer_) {}
473 
475  void convertResult();
476 
478  void convertParam();
479  private:
481  std::vector<char> inputBuffer;
482  };
483 
485  struct Error: public ASql::Error
486  {
487  Error(MYSQL* mysql);
488  Error(MYSQL_STMT* stmt);
489  };
490 
491  extern const char CodeConversionErrorMsg[];
492  }
493 }
494 
495 #endif