fastcgi++
|
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