fastcgi++
query.hpp
Go to the documentation of this file.
00001 #ifndef ASQLQUERY_HPP
00002 #define ASQLQUERY_HPP
00003 
00004 #include <boost/static_assert.hpp>
00005 #include <boost/type_traits/is_base_of.hpp>
00006 #include <boost/utility/enable_if.hpp>
00007 
00008 #include <asql/data.hpp>
00009 #include <asql/exception.hpp>
00010 
00011 namespace ASql
00012 {
00014 
00027    class QueryPar
00028    {
00029    private:
00031       struct SharedData
00032       {
00034          enum Flags { FLAG_SINGLE_PARAMETERS=1, FLAG_SINGLE_RESULTS=1<<1 };
00035 
00037 
00040          SharedData(): m_parameters(0), m_results(0), m_insertId(0), m_rows(0), m_cancel(false), m_flags(0) {}
00047          ~SharedData()
00048          {
00049             delete m_rows;
00050             delete m_insertId;
00051             destroyResults();
00052             destroyParameters();
00053          }
00054 
00056 
00061          void* m_parameters;
00062 
00064 
00068          void* m_results;
00069 
00071          unsigned long long int* m_insertId;
00076          unsigned long long int* m_rows;
00077 
00079          Error m_error;
00080 
00082          boost::function<void()> m_callback;
00083 
00084          boost::mutex m_callbackMutex;
00085 
00087          bool m_cancel;
00088 
00090 
00097          unsigned char m_flags;
00098 
00100 
00103          void destroyResults()
00104          {
00105             if(m_flags&FLAG_SINGLE_RESULTS)
00106                delete static_cast<Data::Set*>(m_results);
00107             else
00108                delete static_cast<Data::SetContainer*>(m_results);
00109             m_results = 0;
00110          }
00111 
00113 
00116          void destroyParameters()
00117          {
00118             if(m_flags&FLAG_SINGLE_PARAMETERS)
00119                delete static_cast<Data::Set*>(m_parameters);
00120             else
00121                delete static_cast<Data::SetContainer*>(m_parameters);
00122             m_parameters = 0;
00123          }
00124       };
00125 
00127       boost::shared_ptr<SharedData> m_sharedData;
00128 
00130 
00136       unsigned char m_flags;
00137 
00138       enum Flags { FLAG_ORIGINAL=1, FLAG_KEEPALIVE=1<<1 };
00139 
00141       void callback()
00142       {
00143          boost::lock_guard<boost::mutex> lock(m_sharedData->m_callbackMutex);
00144          if(!m_sharedData->m_callback.empty())
00145             m_sharedData->m_callback();
00146       }
00147 
00148       void clearResults() { m_sharedData->destroyResults(); } 
00149       void clearParameters() { m_sharedData->destroyParameters(); } 
00150 
00151       template<class T> friend class ConnectionPar;
00152 
00153    protected:
00155 
00159       QueryPar(bool singleParameters, bool singleResults): m_sharedData(new SharedData), m_flags(FLAG_ORIGINAL)
00160       {
00161          if(singleParameters)
00162             m_sharedData->m_flags|=SharedData::FLAG_SINGLE_PARAMETERS;
00163          if(singleResults)
00164             m_sharedData->m_flags|=SharedData::FLAG_SINGLE_RESULTS;
00165       }
00166 
00168 
00174       void setResults(void* results) { m_sharedData->destroyResults(); m_sharedData->m_results=results; }
00175 
00177 
00183       void setParameters(void* parameters) { m_sharedData->destroyParameters(); m_sharedData->m_parameters=parameters; }
00184 
00186 
00195       void* relinquishResults() { void* data = m_sharedData->m_results; m_sharedData->m_results=0; return data; }
00196 
00198 
00207       void* relinquishParameters() { void* data = m_sharedData->m_parameters; m_sharedData->m_parameters=0; return data; }
00208 
00210 
00214       void* results() { return m_sharedData->m_results; }
00215 
00217 
00221       const void* results() const { return m_sharedData->m_results; }
00222 
00224 
00228       void* parameters() { return m_sharedData->m_parameters; }
00229 
00230    public:
00232 
00235       QueryPar(const QueryPar& x): m_sharedData(x.m_sharedData), m_flags(0) {}
00236 
00238       ~QueryPar()
00239       {
00240          // This might seem like we aren't checking for keepalive, but we are
00241          if(m_flags == FLAG_ORIGINAL)
00242             cancel();
00243       }
00244 
00246       unsigned int insertId() const { return m_sharedData->m_insertId?*(m_sharedData->m_insertId):0; }
00247 
00249 
00253       unsigned int rows() const { return m_sharedData->m_rows?*(m_sharedData->m_rows):0; }
00254 
00256       bool busy() const { return m_sharedData.use_count() != 1; }
00257 
00259 
00262       Error error() const { return m_sharedData->m_error; }
00263 
00265 
00268       void setCallback(boost::function<void()> callback=boost::function<void()>())
00269       {
00270          boost::lock_guard<boost::mutex> lock(m_sharedData->m_callbackMutex);
00271          m_sharedData->m_callback = callback;
00272       }
00273 
00275       bool isCallback() { return !m_sharedData->m_callback.empty(); }
00276 
00278       boost::function<void()> getCallback()
00279       {
00280          return m_sharedData->m_callback;
00281       }
00282 
00284 
00287       void keepAlive(bool x) { if(x) m_flags|=FLAG_KEEPALIVE; else m_flags&=~FLAG_KEEPALIVE; }
00288 
00290 
00294       void cancel() { m_sharedData->m_cancel = true; }
00295 
00297       void enableRows()
00298       {
00299          if(!m_sharedData->m_rows)
00300             m_sharedData->m_rows = new unsigned long long;
00301       }
00302 
00304       void enableInsertId()
00305       {
00306          if(!m_sharedData->m_insertId)
00307             m_sharedData->m_insertId = new unsigned long long;
00308       }
00309 
00311       void reset()
00312       {
00313          unsigned char flags = m_sharedData->m_flags;
00314          m_sharedData.reset(new SharedData);
00315          m_sharedData->m_flags = flags;
00316 
00317          m_flags=FLAG_ORIGINAL;
00318          keepAlive(false);
00319       }
00320    };
00321 
00323 
00341    template<class Parameters = void, class Results = void, class ParametersParent = void, class ResultsParent = void>
00342    struct Query: public QueryPar
00343    {
00344       // This default template should never be instanced
00345    private:
00346       Query() {}
00347       Query(const Query& x) {}
00348    };
00349 
00351    template<> struct Query<void, void, void, void>: public QueryPar
00352    {
00353       Query(): QueryPar(true, false) {}
00354       Query(const Query& x): QueryPar(x) {}
00355    };
00356 
00358 
00362    template<class Parameters, class Results>
00363    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
00364    {
00365       Query(): QueryPar(true, true) {}
00366       Query(const Query& x): QueryPar(x) {}
00367 
00369       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00370 
00372       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00373 
00375 
00378       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00379 
00381 
00387       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00388 
00390       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters()));; }
00391 
00393 
00402       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00403 
00405 
00408       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00409 
00411 
00417       void setResults(Results* results) { QueryPar::setResults(results); }
00418 
00420       Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
00421 
00423       const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
00424 
00426 
00435       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
00436    };
00437 
00439 
00443    template<class Parameters, class Results>
00444    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
00445    {
00446       Query(): QueryPar(true, false) {}
00447       Query(const Query& x): QueryPar(x) {}
00448 
00450       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00451 
00453       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00454 
00456 
00459       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00460 
00462 
00468       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00469 
00471       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters()));; }
00472 
00474 
00483       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00484 
00486 
00489       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00490 
00492 
00498       void setResults(Results* results) { QueryPar::setResults(results); }
00499 
00501       Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
00502 
00504       const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
00505 
00507 
00516       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
00517    };
00518 
00520 
00523    template<class Results>
00524    struct Query<void, Results, void,  typename boost::enable_if<boost::is_base_of<Data::Set, Results> >::type>: public QueryPar
00525    {
00526       Query(): QueryPar(true, true) {}
00527       Query(const Query& x): QueryPar(x) {}
00528 
00530       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00531 
00533       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00534 
00536 
00539       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00540 
00542 
00548       void setResults(Results* results) { QueryPar::setResults(results); }
00549 
00551       Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
00552 
00554       const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
00555 
00557 
00566       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
00567    };
00568 
00570 
00573    template<class Results>
00574    struct Query<void, Results, void,  typename boost::enable_if<boost::is_base_of<Data::SetContainer, Results> >::type>: public QueryPar
00575    {
00576       Query(): QueryPar(true, false) {}
00577       Query(const Query& x): QueryPar(x) {}
00578 
00580       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00581 
00583       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00584 
00586 
00589       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00590 
00592 
00598       void setResults(Results* results) { QueryPar::setResults(results); }
00599 
00601       Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
00602 
00604       const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
00605 
00607 
00616       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
00617    };
00618 
00620 
00623    template<class Parameters>
00624    struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::Set, Parameters> >::type, void>: public QueryPar
00625    {
00626       Query(): QueryPar(true, false) {}
00627       Query(const Query& x): QueryPar(x) {}
00628 
00630       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00631 
00633       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00634 
00636 
00639       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00640 
00642 
00648       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00649 
00651       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters()));; }
00652 
00654 
00663       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00664    };
00665 
00667 
00670    template<class Parameters>
00671    struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::SetContainer, Parameters> >::type, void>: public QueryPar
00672    {
00673       Query(): QueryPar(false, false) {}
00674       Query(const Query& x): QueryPar(x) {}
00675 
00677       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00678 
00680       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00681 
00683 
00686       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00687 
00689 
00695       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00696 
00698       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::parameters()));; }
00699 
00701 
00710       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::relinquishParameters())); }
00711    };
00712 }
00713 
00714 #endif