00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef _UESQL_ABSTRACT_CONNECTION_MANAGER__
00027 #define _UESQL_ABSTRACT_CONNECTION_MANAGER__
00028
00029 #include <algorithm>
00030 #include <mpcl/exceptions.hh>
00031 #include <mpcl/text/string.hh>
00032 #include <mpcl/util/collection/map.hh>
00033 #ifdef _UESQL_DEBUG__
00034 #include <mpcl/util/logging/log.hh>
00035 #endif // not _UESQL_DEBUG__
00036 #include <queue>
00037 #include <vector>
00038 #include "defs.hh"
00039
00040
00042 namespace uesqlc
00043 {
00044
00046 template <typename TItem>
00047 struct MUpdateFromBuffer : public std::unary_function<TItem, void>
00048 {
00049
00050 void operator () (TItem* ptITEM) const
00051 {
00052 ptITEM->updateFromBuffer();
00053 }
00054
00055 };
00056
00058 template <typename TItem>
00059 struct MWriteDebugInfo : public std::unary_function<TItem, void>
00060 {
00061
00062 void operator () (TItem* ptITEM) const
00063 {
00064 # ifdef _UESQL_DEBUG__
00065 mpcl::util::logging::tLog << ", " << ptITEM->get();
00066 # endif // not _UESQL_DEBUG__
00067 }
00068
00069 };
00070
00077 template <typename TConnectionData, typename TResult>
00078 class TAbstractConnectionManager : protected TSqlstateDescriptor
00079 {
00080
00081 protected:
00082
00084 typedef
00085 mpcl::util::collection::TMap<mpcl::text::TString, TConnectionData>
00086 TConnectionDataMap;
00087
00089 mutable int iUniqueOrdinal;
00090
00092 TConnectionDataMap tConnectionDataMap;
00093
00095 TConnectionData* ptCurrentConnection;
00096
00098 std::queue<mpcl::text::TString> tInputEmbeddedVariableQueue;
00099
00101 std::vector<IType*> tOutputEmbeddedVariableVector;
00102
00104 mpcl::text::TString yCurrentConnection;
00105
00106
00107 public:
00108
00109
00110
00111
00112
00114 TAbstractConnectionManager (void) :
00115 TSqlstateDescriptor () ,
00116 iUniqueOrdinal (0) ,
00117 tConnectionDataMap () ,
00118 ptCurrentConnection (NULL) ,
00119 tInputEmbeddedVariableQueue () ,
00120 tOutputEmbeddedVariableVector () ,
00121 yCurrentConnection ()
00122 {
00123 initialize();
00124 }
00125
00127 virtual ~TAbstractConnectionManager (void)
00128 {
00129 finish();
00130 }
00131
00138 void bindConnection ( const mpcl::text::TString& rkyCONNECTION_NAME ,
00139 TConnectionData& rtCONNECTION )
00140 {
00141 tConnectionDataMap.bind (rkyCONNECTION_NAME, rtCONNECTION);
00142 }
00143
00150 virtual void diagnose (TResult tRESULT) = 0;
00151
00158 void unbindConnection (const mpcl::text::TString kyCONNECTION_NAME)
00159 {
00160
00161 bool gIsCurrentConnection;
00162 typename TConnectionDataMap::iterator I = tConnectionDataMap.find (kyCONNECTION_NAME);
00163
00164 if ( I == tConnectionDataMap.end() )
00165 {
00166 throw mpcl::TConstraintException ("there is no such connection", __FILE__, __LINE__);
00167 }
00168 else
00169 {
00170 gIsCurrentConnection = ( ptCurrentConnection == &(I->second) );
00171 I->second.close();
00172 tConnectionDataMap.erase (I);
00173 if ( gIsCurrentConnection )
00174 {
00175 yCurrentConnection.erase();
00176 ptCurrentConnection = NULL;
00177 }
00178 }
00179
00180 }
00181
00183 void unbindCurrentConnection (void)
00184 {
00185 if ( existsDefaultConnection() )
00186 {
00187 unbindConnection (yCurrentConnection);
00188 }
00189 }
00190
00192 void unbindAllConnections (void)
00193 {
00194 while ( !tConnectionDataMap.empty() )
00195 {
00196 unbindConnection (tConnectionDataMap.begin()->first);
00197 }
00198 }
00199
00204 virtual void clearQueues (void)
00205 {
00206 while ( !tInputEmbeddedVariableQueue.empty() )
00207 {
00208 tInputEmbeddedVariableQueue.pop();
00209 }
00210 tOutputEmbeddedVariableVector.clear();
00211 }
00212
00218 virtual void clearResult (TResult tRESULT) = 0;
00219
00225 virtual TResult execute (const mpcl::text::TString& rkySTATEMENT)
00226 {
00227 return execute (rkySTATEMENT.c_str());
00228 }
00229
00237 virtual TResult execute ( const mpcl::text::TString& rkySTATEMENT ,
00238 const mpcl::text::TString& rkyCONNECTION_NAME )
00239 {
00240 return execute (rkySTATEMENT.c_str(), rkyCONNECTION_NAME.c_str());
00241 }
00242
00248 virtual TResult execute (const char* pkcSTATEMENT) = 0;
00249
00257 virtual TResult execute ( const char* pkcSTATEMENT ,
00258 const char* pkyCONNECTION_NAME ) = 0;
00259
00266 virtual void executeClean (const char* pkcSTATEMENT)
00267 {
00268 clearResult (execute (pkcSTATEMENT));
00269 }
00270
00272 virtual void finish (void)
00273 {
00274 unbindAllConnections();
00275 clearQueues();
00276 tConnectionDataMap.clear();
00277 yCurrentConnection.erase();
00278 }
00279
00287 virtual IType* getFromOutputQueue (const size_t zINDEX) const
00288 {
00289 if ( zINDEX >= tOutputEmbeddedVariableVector.size() )
00290 {
00291 throw mpcl::TConstraintException ("out of range", __FILE__, __LINE__);
00292 }
00293 return tOutputEmbeddedVariableVector [zINDEX];
00294 }
00295
00297 virtual void initialize (void) {}
00298
00305 mpcl::text::TString instantiate (const char* pkcSTATEMENT);
00306
00313 mpcl::text::TString instantiate (const mpcl::text::TString& rkySTATEMENT)
00314 {
00315 return instantiate (rkySTATEMENT.c_str());
00316 }
00317
00322 virtual void pushOnInputQueue (const IType& rktEMBEDDED_VALUE)
00323 {
00324 tInputEmbeddedVariableQueue.push (rktEMBEDDED_VALUE.get());
00325 }
00326
00331 virtual IType* popFromOutputQueue (void)
00332 {
00333 IType* ptBaseType = tOutputEmbeddedVariableVector.back();
00334
00335 tOutputEmbeddedVariableVector.pop_back();
00336 return ptBaseType;
00337 }
00338
00344 virtual void pushOnOutputQueue (IType* ptSQL_DATA_TYPE)
00345 {
00346 tOutputEmbeddedVariableVector.push_back (ptSQL_DATA_TYPE);
00347 }
00348
00350 void resetStatus (void)
00351 {
00352
00353
00354
00355 SQLCODE = 0;
00356 SQLMESSAGE = "";
00357 SQLSTATE = "00000";
00358 }
00359
00364 void setCurrentConnection (const mpcl::text::TString& rkyCONNECTION_NAME);
00365
00370 virtual void updateOutputVariables (void);
00371
00372
00373 public:
00374
00375
00376
00377
00378
00383 TConnectionData& getCurrentConnectionData (void)
00384 {
00385 if ( ptCurrentConnection == NULL )
00386 {
00387 throw mpcl::TConstraintException ("there is no current connection", __FILE__, __LINE__);
00388 }
00389 return *ptCurrentConnection;
00390 }
00391
00396 const mpcl::text::TString& currentConnectionName (void) const
00397 {
00398 return yCurrentConnection;
00399 }
00400
00405 virtual bool existsDefaultConnection (void) const
00406 {
00407 return ( ptCurrentConnection != NULL );
00408 }
00409
00415 bool isConnected (const mpcl::text::TString& rkyCONNECTION_NAME) const
00416 {
00417 return tConnectionDataMap.isBound (rkyCONNECTION_NAME);
00418 }
00419
00424 bool isNotFoundCondition (void) const
00425 {
00426 return ( SQLSTATE == no_data::pkcNO_SUBCLASS );
00427 }
00428
00433 bool isSqlerrorCondition (void) const
00434 {
00435 return ( SQLCODE < 0 );
00436 }
00437
00438 };
00439
00440 }
00441
00442
00443
00444
00445
00446
00447 template <typename TConnectionData, typename TResult>
00448 inline mpcl::text::TString uesqlc::TAbstractConnectionManager<TConnectionData, TResult>::
00449 instantiate (const char* pkcSTATEMENT)
00450 {
00451
00452 using mpcl::text::TString;
00453
00454 register TString::size_type zPatternOffset;
00455 TString yStatementInstance (pkcSTATEMENT);
00456
00457 while ( !tInputEmbeddedVariableQueue.empty() )
00458 {
00459 if ( TString::npos == (zPatternOffset = yStatementInstance.find ("$z")) )
00460 {
00461 break;
00462 }
00463 else
00464 {
00465 yStatementInstance.replace (zPatternOffset, 2, tInputEmbeddedVariableQueue.front());
00466 tInputEmbeddedVariableQueue.pop();
00467 }
00468 }
00469 return yStatementInstance;
00470
00471 }
00472
00473
00474 template <typename TConnectionData, typename TResult>
00475 inline void uesqlc::TAbstractConnectionManager<TConnectionData, TResult>::
00476 setCurrentConnection (const mpcl::text::TString& rkyCONNECTION_NAME)
00477 {
00478
00479 if ( tConnectionDataMap.isBound (rkyCONNECTION_NAME) )
00480 {
00481 yCurrentConnection = rkyCONNECTION_NAME;
00482 ptCurrentConnection = &(tConnectionDataMap [rkyCONNECTION_NAME]);
00483 # ifdef _UESQL_DEBUG__
00484 mpcl::util::logging::tLog << mpcl::util::logging::header << "SET CONNECTION '" << rkyCONNECTION_NAME << "';\n";
00485 # endif // not _UESQL_DEBUG__
00486 resetStatus();
00487 }
00488 else
00489 {
00490
00491
00492
00493
00494 SQLCODE = -1;
00495 SQLMESSAGE = "";
00496 SQLSTATE = "08003";
00497 }
00498
00499 }
00500
00501
00502 template <typename TConnectionData, typename TResult>
00503 inline void uesqlc::TAbstractConnectionManager<TConnectionData, TResult>::
00504 updateOutputVariables (void)
00505 {
00506
00507 # ifdef _UESQL_DEBUG__
00508 using mpcl::util::logging::header;
00509 using mpcl::util::logging::tLog;
00510 # endif // not _UESQL_DEBUG__
00511 using std::for_each;
00512
00513 for_each ( tOutputEmbeddedVariableVector.begin() ,
00514 tOutputEmbeddedVariableVector.end() ,
00515 MUpdateFromBuffer<IType>() );
00516 # ifdef _UESQL_DEBUG__
00517 tLog << header << "FETCHED (";
00518 if ( !tOutputEmbeddedVariableVector.empty() )
00519 {
00520 tLog << tOutputEmbeddedVariableVector.front()->get();
00521 for_each ( tOutputEmbeddedVariableVector.begin() + 1 ,
00522 tOutputEmbeddedVariableVector.end() ,
00523 MWriteDebugInfo<IType>() );
00524 }
00525 tLog << ");\n";
00526 # endif // not _UESQL_DEBUG__
00527
00528 }
00529
00530
00531 #endif // not _UESQL_ABSTRACT_CONNECTION_MANAGER__