fastcgi++
query.hpp
Go to the documentation of this file.
1 #ifndef ASQLQUERY_HPP
2 #define ASQLQUERY_HPP
3 
4 #include <boost/static_assert.hpp>
5 #include <boost/type_traits/is_base_of.hpp>
6 #include <boost/utility/enable_if.hpp>
7 
8 #include <asql/data.hpp>
9 #include <asql/exception.hpp>
10 
11 namespace ASql
12 {
14 
27  class QueryPar
28  {
29  private:
31  struct SharedData
32  {
35 
37 
48  {
49  delete m_rows;
50  delete m_insertId;
53  }
54 
56 
61  void* m_parameters;
62 
64 
68  void* m_results;
69 
71  unsigned long long int* m_insertId;
76  unsigned long long int* m_rows;
77 
80 
82  boost::function<void()> m_callback;
83 
84  boost::mutex m_callbackMutex;
85 
87  bool m_cancel;
88 
90 
97  unsigned char m_flags;
98 
100 
104  {
106  delete static_cast<Data::Set*>(m_results);
107  else
108  delete static_cast<Data::SetContainer*>(m_results);
109  m_results = 0;
110  }
111 
113 
117  {
119  delete static_cast<Data::Set*>(m_parameters);
120  else
121  delete static_cast<Data::SetContainer*>(m_parameters);
122  m_parameters = 0;
123  }
124  };
125 
127  boost::shared_ptr<SharedData> m_sharedData;
128 
130 
136  unsigned char m_flags;
137 
139 
141  void callback()
142  {
143  boost::lock_guard<boost::mutex> lock(m_sharedData->m_callbackMutex);
144  if(!m_sharedData->m_callback.empty())
145  m_sharedData->m_callback();
146  }
147 
148  void clearResults() { m_sharedData->destroyResults(); }
149  void clearParameters() { m_sharedData->destroyParameters(); }
150 
151  template<class T> friend class ConnectionPar;
152 
153  protected:
155 
159  QueryPar(bool singleParameters, bool singleResults): m_sharedData(new SharedData), m_flags(FLAG_ORIGINAL)
160  {
161  if(singleParameters)
163  if(singleResults)
165  }
166 
168 
174  void setResults(void* results) { m_sharedData->destroyResults(); m_sharedData->m_results=results; }
175 
177 
183  void setParameters(void* parameters) { m_sharedData->destroyParameters(); m_sharedData->m_parameters=parameters; }
184 
186 
195  void* relinquishResults() { void* data = m_sharedData->m_results; m_sharedData->m_results=0; return data; }
196 
198 
207  void* relinquishParameters() { void* data = m_sharedData->m_parameters; m_sharedData->m_parameters=0; return data; }
208 
210 
214  void* results() { return m_sharedData->m_results; }
215 
217 
221  const void* results() const { return m_sharedData->m_results; }
222 
224 
228  void* parameters() { return m_sharedData->m_parameters; }
229 
231 
235  const void* parameters() const { return m_sharedData->m_parameters; }
236 
237  public:
239 
243 
246  {
247  // This might seem like we aren't checking for keepalive, but we are
248  if(m_flags == FLAG_ORIGINAL)
249  cancel();
250  }
251 
253  unsigned int insertId() const { return m_sharedData->m_insertId?*(m_sharedData->m_insertId):0; }
254 
256 
260  unsigned int rows() const { return m_sharedData->m_rows?*(m_sharedData->m_rows):0; }
261 
263  bool busy() const { return m_sharedData.use_count() != 1; }
264 
266 
269  Error error() const { return m_sharedData->m_error; }
270 
272 
275  void setCallback(boost::function<void()> callback=boost::function<void()>())
276  {
277  boost::lock_guard<boost::mutex> lock(m_sharedData->m_callbackMutex);
278  m_sharedData->m_callback = callback;
279  }
280 
282  bool isCallback() { return !m_sharedData->m_callback.empty(); }
283 
285  boost::function<void()> getCallback()
286  {
287  return m_sharedData->m_callback;
288  }
289 
291 
294  void keepAlive(bool x) { if(x) m_flags|=FLAG_KEEPALIVE; else m_flags&=~FLAG_KEEPALIVE; }
295 
297 
301  void cancel() { m_sharedData->m_cancel = true; }
302 
304  void enableRows()
305  {
306  if(!m_sharedData->m_rows)
307  m_sharedData->m_rows = new unsigned long long;
308  }
309 
312  {
313  if(!m_sharedData->m_insertId)
314  m_sharedData->m_insertId = new unsigned long long;
315  }
316 
318  void reset()
319  {
320  unsigned char flags = m_sharedData->m_flags;
321  m_sharedData.reset(new SharedData);
322  m_sharedData->m_flags = flags;
323 
325  keepAlive(false);
326  }
327  };
328 
330 
348  template<class Parameters = void, class Results = void, class ParametersParent = void, class ResultsParent = void>
349  struct Query: public QueryPar
350  {
351  // This default template should never be instanced
352  private:
353  Query() {}
354  Query(const Query& x) {}
355  };
356 
358  template<> struct Query<void, void, void, void>: public QueryPar
359  {
360  Query(): QueryPar(true, false) {}
361  Query(const Query& x): QueryPar(x) {}
362  };
363 
365 
369  template<class Parameters, class Results>
370  struct Query<Parameters, Results, typename boost::enable_if<boost::is_base_of<Data::Set, Parameters> >::type, typename boost::enable_if<boost::is_base_of<Data::Set, Results> >::type>: public QueryPar
371  {
372  Query(): QueryPar(true, true) {}
373  Query(const Query& x): QueryPar(x) {}
374 
376  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
377 
379  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
380 
382 
385  Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
386 
388 
394  void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
395 
397  Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters())); }
398 
400  const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
401 
403 
412  Parameters* relinquishParameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
413 
415 
418  Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
419 
421 
427  void setResults(Results* results) { QueryPar::setResults(results); }
428 
430  Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
431 
433  const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
434 
436 
445  Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
446  };
447 
449 
453  template<class Parameters, class Results>
454  struct Query<Parameters, Results, typename boost::enable_if<boost::is_base_of<Data::Set, Parameters> >::type, typename boost::enable_if<boost::is_base_of<Data::SetContainer, Results> >::type>: public QueryPar
455  {
456  Query(): QueryPar(true, false) {}
457  Query(const Query& x): QueryPar(x) {}
458 
460  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
461 
463  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
464 
466 
469  Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
470 
472 
478  void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
479 
481  Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters())); }
482 
484  const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
485 
487 
496  Parameters* relinquishParameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
497 
499 
502  Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
503 
505 
511  void setResults(Results* results) { QueryPar::setResults(results); }
512 
514  Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
515 
517  const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
518 
520 
529  Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
530  };
531 
533 
536  template<class Results>
537  struct Query<void, Results, void, typename boost::enable_if<boost::is_base_of<Data::Set, Results> >::type>: public QueryPar
538  {
539  Query(): QueryPar(true, true) {}
540  Query(const Query& x): QueryPar(x) {}
541 
543  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
544 
546  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
547 
549 
552  Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
553 
555 
561  void setResults(Results* results) { QueryPar::setResults(results); }
562 
564  Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
565 
567  const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
568 
570 
579  Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
580  };
581 
583 
586  template<class Results>
587  struct Query<void, Results, void, typename boost::enable_if<boost::is_base_of<Data::SetContainer, Results> >::type>: public QueryPar
588  {
589  Query(): QueryPar(true, false) {}
590  Query(const Query& x): QueryPar(x) {}
591 
593  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
594 
596  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
597 
599 
602  Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
603 
605 
611  void setResults(Results* results) { QueryPar::setResults(results); }
612 
614  Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
615 
617  const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
618 
620 
629  Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
630  };
631 
633 
636  template<class Parameters>
637  struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::Set, Parameters> >::type, void>: public QueryPar
638  {
639  Query(): QueryPar(true, false) {}
640  Query(const Query& x): QueryPar(x) {}
641 
643  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
644 
646  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
647 
649 
652  Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
653 
655  const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
656 
658 
664  void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
665 
667  Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters()));; }
668 
670 
679  Parameters* relinquishParameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
680  };
681 
683 
686  template<class Parameters>
687  struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::SetContainer, Parameters> >::type, void>: public QueryPar
688  {
689  Query(): QueryPar(false, false) {}
690  Query(const Query& x): QueryPar(x) {}
691 
693  static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
694 
696  static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
697 
699 
702  Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
703 
705 
711  void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
712 
714  Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::parameters())); }
715 
717  const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::SetContainer*)(QueryPar::parameters())); }
718 
720 
729  Parameters* relinquishParameters() { return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::relinquishParameters())); }
730  };
731 }
732 
733 #endif