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 
00231 
00235       const void* parameters() const { return m_sharedData->m_parameters; }
00236 
00237    public:
00239 
00242       QueryPar(const QueryPar& x): m_sharedData(x.m_sharedData), m_flags(0) {}
00243 
00245       ~QueryPar()
00246       {
00247          // This might seem like we aren't checking for keepalive, but we are
00248          if(m_flags == FLAG_ORIGINAL)
00249             cancel();
00250       }
00251 
00253       unsigned int insertId() const { return m_sharedData->m_insertId?*(m_sharedData->m_insertId):0; }
00254 
00256 
00260       unsigned int rows() const { return m_sharedData->m_rows?*(m_sharedData->m_rows):0; }
00261 
00263       bool busy() const { return m_sharedData.use_count() != 1; }
00264 
00266 
00269       Error error() const { return m_sharedData->m_error; }
00270 
00272 
00275       void setCallback(boost::function<void()> callback=boost::function<void()>())
00276       {
00277          boost::lock_guard<boost::mutex> lock(m_sharedData->m_callbackMutex);
00278          m_sharedData->m_callback = callback;
00279       }
00280 
00282       bool isCallback() { return !m_sharedData->m_callback.empty(); }
00283 
00285       boost::function<void()> getCallback()
00286       {
00287          return m_sharedData->m_callback;
00288       }
00289 
00291 
00294       void keepAlive(bool x) { if(x) m_flags|=FLAG_KEEPALIVE; else m_flags&=~FLAG_KEEPALIVE; }
00295 
00297 
00301       void cancel() { m_sharedData->m_cancel = true; }
00302 
00304       void enableRows()
00305       {
00306          if(!m_sharedData->m_rows)
00307             m_sharedData->m_rows = new unsigned long long;
00308       }
00309 
00311       void enableInsertId()
00312       {
00313          if(!m_sharedData->m_insertId)
00314             m_sharedData->m_insertId = new unsigned long long;
00315       }
00316 
00318       void reset()
00319       {
00320          unsigned char flags = m_sharedData->m_flags;
00321          m_sharedData.reset(new SharedData);
00322          m_sharedData->m_flags = flags;
00323 
00324          m_flags=FLAG_ORIGINAL;
00325          keepAlive(false);
00326       }
00327    };
00328 
00330 
00348    template<class Parameters = void, class Results = void, class ParametersParent = void, class ResultsParent = void>
00349    struct Query: public QueryPar
00350    {
00351       // This default template should never be instanced
00352    private:
00353       Query() {}
00354       Query(const Query& x) {}
00355    };
00356 
00358    template<> struct Query<void, void, void, void>: public QueryPar
00359    {
00360       Query(): QueryPar(true, false) {}
00361       Query(const Query& x): QueryPar(x) {}
00362    };
00363 
00365 
00369    template<class Parameters, class Results>
00370    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
00371    {
00372       Query(): QueryPar(true, true) {}
00373       Query(const Query& x): QueryPar(x) {}
00374 
00376       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00377 
00379       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00380 
00382 
00385       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00386 
00388 
00394       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00395 
00397       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters())); }
00398 
00400       const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
00401 
00403 
00412       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00413 
00415 
00418       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00419 
00421 
00427       void setResults(Results* results) { QueryPar::setResults(results); }
00428 
00430       Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
00431 
00433       const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
00434 
00436 
00445       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
00446    };
00447 
00449 
00453    template<class Parameters, class Results>
00454    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
00455    {
00456       Query(): QueryPar(true, false) {}
00457       Query(const Query& x): QueryPar(x) {}
00458 
00460       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00461 
00463       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00464 
00466 
00469       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00470 
00472 
00478       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00479 
00481       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters())); }
00482 
00484       const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
00485 
00487 
00496       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00497 
00499 
00502       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00503 
00505 
00511       void setResults(Results* results) { QueryPar::setResults(results); }
00512 
00514       Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
00515 
00517       const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
00518 
00520 
00529       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
00530    };
00531 
00533 
00536    template<class Results>
00537    struct Query<void, Results, void,  typename boost::enable_if<boost::is_base_of<Data::Set, Results> >::type>: public QueryPar
00538    {
00539       Query(): QueryPar(true, true) {}
00540       Query(const Query& x): QueryPar(x) {}
00541 
00543       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00544 
00546       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00547 
00549 
00552       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00553 
00555 
00561       void setResults(Results* results) { QueryPar::setResults(results); }
00562 
00564       Results* results() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::results())); }
00565 
00567       const Results* results() const { return static_cast<const Results*>((const ASql::Data::Set*)(QueryPar::results())); }
00568 
00570 
00579       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::Set*)(QueryPar::relinquishResults())); }
00580    };
00581 
00583 
00586    template<class Results>
00587    struct Query<void, Results, void,  typename boost::enable_if<boost::is_base_of<Data::SetContainer, Results> >::type>: public QueryPar
00588    {
00589       Query(): QueryPar(true, false) {}
00590       Query(const Query& x): QueryPar(x) {}
00591 
00593       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00594 
00596       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00597 
00599 
00602       Results& createResults() { Results* results=new Results; QueryPar::setResults(results); return *results; }
00603 
00605 
00611       void setResults(Results* results) { QueryPar::setResults(results); }
00612 
00614       Results* results() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::results())); }
00615 
00617       const Results* results() const { return static_cast<const Results*>((const ASql::Data::SetContainer*)(QueryPar::results())); }
00618 
00620 
00629       Results* relinquishResults() { return static_cast<Results*>((ASql::Data::SetContainer*)(QueryPar::relinquishResults())); }
00630    };
00631 
00633 
00636    template<class Parameters>
00637    struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::Set, Parameters> >::type, void>: public QueryPar
00638    {
00639       Query(): QueryPar(true, false) {}
00640       Query(const Query& x): QueryPar(x) {}
00641 
00643       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00644 
00646       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00647 
00649 
00652       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00653 
00655       const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::Set*)(QueryPar::parameters())); }
00656 
00658 
00664       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00665 
00667       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::parameters()));; }
00668 
00670 
00679       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::Set*)(QueryPar::relinquishParameters())); }
00680    };
00681 
00683 
00686    template<class Parameters>
00687    struct Query<Parameters, void, typename boost::enable_if<boost::is_base_of<Data::SetContainer, Parameters> >::type, void>: public QueryPar
00688    {
00689       Query(): QueryPar(false, false) {}
00690       Query(const Query& x): QueryPar(x) {}
00691 
00693       static Query& staticRebuild(QueryPar& x) { return static_cast<Query&>(x); }
00694 
00696       static Query& dynamicRebuild(QueryPar& x) { return dynamic_cast<Query&>(x); }
00697 
00699 
00702       Parameters& createParameters() { Parameters* parameters=new Parameters; QueryPar::setParameters(parameters); return *parameters; }
00703 
00705 
00711       void setParameters(Parameters* parameters) { QueryPar::setParameters(parameters); }
00712 
00714       Parameters* parameters() { return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::parameters())); }
00715 
00717       const Parameters* parameters() const { return static_cast<const Parameters*>((const ASql::Data::SetContainer*)(QueryPar::parameters())); }
00718 
00720 
00729       Parameters* relinquishParameters() {  return static_cast<Parameters*>((ASql::Data::SetContainer*)(QueryPar::relinquishParameters())); }
00730    };
00731 }
00732 
00733 #endif