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