Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbiResult.cxx

Go to the documentation of this file.
00001 // $Id: DbiResult.cxx,v 1.23 2006/08/08 10:51:32 west Exp $
00002 
00003 #include <sstream>
00004 
00005 #include "DatabaseInterface/DbiBinaryFile.h"
00006 #include "DatabaseInterface/DbiResultKey.h"
00007 #include "DatabaseInterface/DbiRecord.h"
00008 #include "DatabaseInterface/DbiResult.h"
00009 #include "DatabaseInterface/DbiResultSet.h"
00010 #include "DatabaseInterface/DbiServices.h"
00011 #include "DatabaseInterface/DbiTableRow.h"
00012 #include "LeakChecker/Lea.h"
00013 #include "MessageService/MsgService.h"
00014 
00015 ClassImp(DbiResult)
00016 
00017 //   Definition of static data members
00018 //   *********************************
00019 
00020  Int_t DbiResult::fgLastID(0);      
00021 
00022 CVSID("$Id: DbiResult.cxx,v 1.23 2006/08/08 10:51:32 west Exp $");
00023 //  Global functions
00024 //  *****************
00025 
00026 //.....................................................................
00027 
00028 DbiBinaryFile& operator<<(DbiBinaryFile& bf, const DbiResult& res) {
00029 
00030 // Writing is a const operation, but uses a non-const method, so cast away const.
00031 
00032   DbiResult& res_tmp = const_cast< DbiResult&>(res);
00033   res_tmp.Streamer(bf);
00034   return bf;
00035 }
00036 
00037 //.....................................................................
00038 
00039 DbiBinaryFile& operator>>(DbiBinaryFile& bf, DbiResult& res) {
00040 
00041   res.Streamer(bf);
00042   return bf;
00043 }
00044 
00045 // Definition of member functions (alphabetical order)
00046 // ***************************************************
00047 
00048 
00049 //.....................................................................
00050 
00051 DbiResult::DbiResult(DbiResultSet* resultSet,
00052                      const DbiValidityRec* vrec,
00053                      const string& sqlQualifiers) :
00054 fID(++fgLastID),
00055 fCanReuse(kTRUE),
00056 fEffVRec(0),
00057 fKey(0),
00058 fResultsFromDb(kFALSE),
00059 fNumClients(0),
00060 fTableName("Unknown"),
00061 fSqlQualifiers(sqlQualifiers)
00062 {
00063 //
00064 //
00065 //  Purpose:  Default constructor
00066 //
00067 //  Arguments: 
00068 //      resultSet     in   Pointer DbiResultSet from query. May be null.  
00069 //      vrec          in   Pointer to validity record from query. 
00070 //                         May be null
00071 //      sqlQualifier  in   Extended Context sql qualifiers
00072 //
00073 //  Return:    n/a
00074 //
00075 //  Contact:   N. West
00076 //
00077 //  Specification:-
00078 //  =============
00079 //
00080 //  o Create Result from DbiResultSet generated by query.
00081 
00082 
00083 //  Program Notes:-
00084 //  =============
00085 
00086 // None.
00087 
00088   LEA_CTOR    //Leak Checker
00089 
00090   MSG("Dbi", Msg::kVerbose) << "Creating DbiResult" << endl;
00091 
00092   if ( vrec ) fEffVRec = *vrec;
00093   if ( resultSet ) fTableName = resultSet->TableNameTc();
00094  
00095 }
00096 
00097 //.....................................................................
00098 
00099 DbiResult::~DbiResult() {
00100 //
00101 //
00102 //  Purpose: Destructor
00103 //
00104 //  Arguments: 
00105 //    None.
00106 //
00107 //  Return:    n/a
00108 //
00109 //  Contact:   N. West
00110 //
00111 //  Specification:-
00112 //  =============
00113 //
00114 //  o  Destroy Result.
00115 
00116 
00117 //  Program Notes:-
00118 //  =============
00119 
00120 //  None.
00121 
00122   LEA_DTOR    //Leak Checker
00123 
00124   MSG("Dbi", Msg::kVerbose) << "Destroying DbiResult." << endl;
00125 
00126   if ( fNumClients ) MSG("Dbi", Msg::kWarning) 
00127     << "Warning: Destroying DbiResult with " << fNumClients 
00128     << " clients " << endl;
00129 
00130   this->DeRegisterKey();
00131 
00132 }
00133 //.....................................................................
00134 
00135 void DbiResult::BuildLookUpTable() const {
00136 //
00137 //
00138 //  Purpose:  Build look-up Natural Index -> TableRow.
00139 //
00140 //  Contact:   N. West
00141 //
00142 //  Program Notes:-
00143 //  =============
00144 //
00145 //  This member function assumes that the sub-class can support
00146 //  the GetTableRow(...) and GetNumRows methods so take care if 
00147 //  called in the sub-class ctor.
00148 
00149 //  Extended Context serach can produce duplicates.
00150   Bool_t duplicatesOK = this->IsExtendedContext();
00151 
00152   MSG("Dbi", Msg::kVerbose) << "Building look-uptable. Allow duplicates: " 
00153                             << duplicatesOK << endl;
00154 
00155   for ( Int_t rowNo = this->GetNumRows()-1; 
00156         rowNo >= 0;
00157         --rowNo ) {
00158     const DbiTableRow* row  = this->GetTableRow(rowNo);
00159     UInt_t index            = row->GetIndex(rowNo);
00160 //  Ensure we use this class's GetTableRowByIndex, the method is
00161 //  virtual but if the subclass has called this method then it must
00162 //  be the right one to use. [Actually DbiResultAgg overrides
00163 //  GetTableRowByIndex, but only to make building lazy].
00164     const DbiTableRow* row2 = this->DbiResult::GetTableRowByIndex(index);
00165 
00166     MSG("Dbi", Msg::kVerbose)
00167           << "Look-up. Row no " << rowNo
00168           << " index " << index 
00169           << " row,row2 " << (void*) row << "," << (void*) row2 << endl;
00170    
00171     if ( row2 != 0 && row2 != row && ! duplicatesOK ) {
00172       std::ostringstream msg;
00173       msg << "Duplicated row natural index: " << index  
00174           << " Found at row " <<  rowNo
00175           << " of table " <<  this->TableName()
00176           << ":-\n     index of agg " <<  row->GetAggregateNo();
00177       if ( row->GetOwner() ) msg << "(SEQNO " << row->GetOwner()->GetValidityRec(row).GetSeqNo() << ")";
00178       msg << " matches agg " <<  row2->GetAggregateNo();
00179       if ( row2->GetOwner() ) msg << "(SEQNO " << row2->GetOwner()->GetValidityRec(row2).GetSeqNo() << ")";
00180       MAXMSG("Dbi",Msg::kError,20) << msg.str() << endl;
00181    }
00182 
00183     else  fIndexKeys[index] = row;
00184   }  
00185 
00186 }
00187 
00188 //.....................................................................
00189 
00190 Bool_t DbiResult::CanDelete(const DbiResult* res) {
00191 //
00192 //
00193 //  Purpose:  See if suitable for deleting.
00194 //
00195 //  Arguments: 
00196 //    res          in    A DbiResult that is currently used. 
00197 //                       Optional: default = 0.
00198 
00199 //  If the query would be satisfied apart from the date, then
00200 //  assume we have moved out of the validity window, never
00201 //  to return!
00202 
00203   if (     res 
00204         && this->CanReuse() 
00205         && this->GetValidityRec().HasExpired(res->GetValidityRec()) 
00206      )  this->SetCanReuse(kFALSE);
00207 
00208   return ! this->GetNumClients() && ! this->CanReuse();
00209 }
00210 
00211 //.....................................................................
00212 
00213 void DbiResult::CaptureExceptionLog(UInt_t startFrom) {
00214 //
00215 //
00216 //  Purpose: Capture Exception Log from latest entries in Global Exception Log. 
00217 
00218   fExceptionLog.Clear();
00219   DbiExceptionLog::GetGELog().Copy(fExceptionLog,startFrom);
00220 
00221 }
00222 
00223 //.....................................................................
00224 
00225 void DbiResult::DeRegisterKey() {
00226 //
00227 //
00228 //  Purpose: Deregister key if it exists. 
00229 
00230   if ( ! fKey ) return;
00231 
00232   DbiRecord* record = DbiServices::GetRecord();
00233   if ( ! record ) {
00234     MSG("Dbi",Msg::kWarning) << "Attempting to deregister DbiResultKey at " << (void*) fKey 
00235                              << " but owning DbiRecord cannot be found." << endl; 
00236   }
00237   else {
00238     record->DeleteKey(fKey);
00239     fKey = 0;
00240   }
00241 
00242 }
00243 //.....................................................................
00244 
00245 const DbiResultKey* DbiResult::GetKey() const {
00246 
00247 //  Purpose:  Get the associated DbiResultKey, or an empty one if none exists.
00248 
00249   return fKey ? fKey : DbiResultKey::GetEmptyKey();
00250 
00251 }
00252 
00253 //.....................................................................
00254 
00255 const DbiTableRow* DbiResult::GetTableRowByIndex(UInt_t index) const {
00256 //
00257 //
00258 //  Purpose:  Return row corresponding to Natural Index (or 0 if none)
00259 //
00260 //  Contact:   N. West
00261 //
00262 
00263 // Use Find rather than operator[] to avoid creating entry 
00264 // if index missing
00265   IndexToRow_t::const_iterator idx = fIndexKeys.find(index);
00266   return ( idx == fIndexKeys.end() ) ? 0 : (*idx).second;
00267 
00268 }
00269 
00270 //.....................................................................
00271 
00272 void DbiResult::RegisterKey() {
00273 //
00274 //
00275 //  Purpose: Create and register key if set not empty and not already done. 
00276 
00277   if ( fKey || this->GetNumRows() == 0) return;
00278 
00279   DbiRecord* record = DbiServices::GetRecord();
00280   if ( ! record ) {
00281     MSG("Dbi",Msg::kWarning) << "cannot create and register key"
00282                              << ", owning DbiRecord cannot be found." << endl; 
00283   }
00284   else {
00285     DbiResultKey* key = this->CreateKey();
00286     record->AdoptKey(key);
00287     fKey = key;
00288   }
00289 
00290 }
00291 //.....................................................................
00292 
00293 Bool_t DbiResult::Satisfies(const VldContext& vc,
00294                             const Dbi::Task& task) {
00295 //
00296 //
00297 //  Purpose:  Check to see if this Result satisfies specific context query.
00298 //
00299 //  Arguments: 
00300 //    vc           in    Context of query
00301 //    task         in    Task of query
00302 //
00303 //  Return:    kTRUE if can satisfy query.
00304 //
00305 //  Contact:   N. West
00306 //
00307 //  Program Notes:-
00308 //  =============
00309 
00310 //  If it cannot satisfy the query in a way that suggests 
00311 //  that its unlikely that it will satisfy future queries
00312 //  then mark as cannot reuse so that it becomes eligible
00313 //  for purging.
00314 
00315 // Extended Context queries cannot satisfy specific context queries.
00316 
00317   Bool_t isExtendedContext = this->IsExtendedContext();
00318   Bool_t canReuse          = this->CanReuse();
00319   Bool_t isCompatible      = this->GetValidityRec().IsCompatible(vc,task);
00320   Bool_t hasExpired        = this->GetValidityRec().HasExpired(vc,task);
00321   UInt_t numClients        = this->GetNumClients();
00322   MSG("Dbi",Msg::kDebug) 
00323     << "    Checking result with DbiValidityRec:- \n      " << this->GetValidityRec()
00324     << "  With extended context: " << isExtendedContext
00325     << " CanReuse: " << canReuse
00326     << " Is Compatible: " << isCompatible
00327     << " HasExpired: " <<  hasExpired
00328     << " number of clients: " << numClients
00329     << endl;
00330 
00331   if ( isExtendedContext ) return kFALSE;
00332 
00333   if ( canReuse && isCompatible )  return kTRUE;
00334     
00335 //  If the query would be satisfied apart from the date, then
00336 //  assume we have moved out of the validity window, never
00337 //  to return!
00338 
00339   if ( canReuse && hasExpired && numClients == 0 )  {
00340     MSG("Dbi",Msg::kDebug) << "    Marking result as not reusable" << endl;
00341    this-> SetCanReuse(kFALSE);
00342   }
00343 
00344   return kFALSE;
00345 
00346 }
00347 //.....................................................................
00348 
00349 void DbiResult::Streamer(DbiBinaryFile& file) {
00350 //
00351 //
00352 //  Purpose:  I/O to binary file
00353 //
00354 //  Program Notes:-
00355 //  =============
00356 
00357 //  Don't store fIndexKeys; it will be rebuilt on input by the subclass.
00358 
00359   if ( file.IsReading() ) {
00360     MSG("Dbi", Msg::kDebug) << "    Restoring DbiResult ..." << endl;
00361     file >> fCanReuse;
00362     fEffVRec.Streamer(file);
00363     MSG("Dbi", Msg::kVerbose) << "    Restored " << fEffVRec << endl;
00364     fResultsFromDb = kFALSE;
00365     fNumClients    = 0;
00366     file >> fTableName;
00367     MSG("Dbi", Msg::kVerbose) << "    Restored string " << fTableName << endl;
00368   }
00369   else if ( file.IsWriting() ) {
00370     MSG("Dbi", Msg::kDebug) << "    Saving DbiResult ..." << endl;
00371     file << fCanReuse;
00372     MSG("Dbi", Msg::kVerbose) << "    Saving " << fEffVRec << endl;
00373     fEffVRec.Streamer(file);
00374     MSG("Dbi", Msg::kVerbose) << "    Saving string " << fTableName << endl;
00375     file << fTableName;
00376   }
00377 }
00378 
00379 /*    Template for New Member Function
00380 
00381 //.....................................................................
00382 
00383 DbiResult:: {
00384 //
00385 //
00386 //  Purpose:  
00387 //
00388 //  Arguments: 
00389 //    xxxxxxxxx    in    yyyyyy
00390 //
00391 //  Return:    
00392 //
00393 //  Contact:   N. West
00394 //
00395 //  Specification:-
00396 //  =============
00397 //
00398 //  o 
00399 
00400 //  Program Notes:-
00401 //  =============
00402 
00403 //  None.
00404 
00405 
00406 }
00407 
00408 */
00409 

Generated on Mon Jun 16 14:56:55 2008 for loon by  doxygen 1.3.9.1