// $Id: IDbiResultSet.cxx,v 1.2 2011/06/08 09:49:18 finch Exp $ #include #include "IDbiBinaryFile.hxx" #include "IDbiResultKey.hxx" #include "IDbiResultSet.hxx" #include "IDbiInRowStream.hxx" #include "IDbiServices.hxx" #include "IDbiTableRow.hxx" #include #include using std::endl; ClassImp(COMET::IDbiResultSet) // Definition of static data members // ********************************* Int_t COMET::IDbiResultSet::fgLastID(0); // Global functions // ***************** //..................................................................... COMET::IDbiBinaryFile& operator<<(COMET::IDbiBinaryFile& bf, const COMET::IDbiResultSet& res) { // Writing is a const operation, but uses a non-const method, so cast away const. COMET::IDbiResultSet& res_tmp = const_cast< COMET::IDbiResultSet&>(res); res_tmp.Streamer(bf); return bf; } //..................................................................... COMET::IDbiBinaryFile& operator>>(COMET::IDbiBinaryFile& bf, COMET::IDbiResultSet& res) { res.Streamer(bf); return bf; } // Definition of member functions (alphabetical order) // *************************************************** //..................................................................... COMET::IDbiResultSet::IDbiResultSet(COMET::IDbiInRowStream* resultSet, const COMET::IDbiValidityRec* vrec, const string& sqlQualifiers) : fID(++fgLastID), fCanReuse(kTRUE), fEffVRec(0), fKey(0), fResultsFromDb(kFALSE), fNumClients(0), fTableName("Unknown"), fSqlQualifiers(sqlQualifiers) { // // // Purpose: Default constructor // // Arguments: // resultSet in Pointer COMET::IDbiInRowStream from query. May be null. // vrec in Pointer to validity record from query. // May be null // sqlQualifier in Extended Context sql qualifiers // // Return: n/a // // Contact: N. West // // Specification:- // ============= // // o Create Result from COMET::IDbiInRowStream generated by query. // Program Notes:- // ============= // None. COMETTrace( "Creating COMET::IDbiResultSet" << " "); if ( vrec ) fEffVRec = *vrec; if ( resultSet ) fTableName = resultSet->TableNameTc(); } //..................................................................... COMET::IDbiResultSet::~IDbiResultSet() { // // // Purpose: Destructor // // Arguments: // None. // // Return: n/a // // Contact: N. West // // Specification:- // ============= // // o Destroy Result. // Program Notes:- // ============= // None. COMETTrace( "Destroying COMET::IDbiResultSet." << " "); if ( fNumClients ) COMETWarn( "Warning: Destroying COMET::IDbiResultSet with " << fNumClients << " clients " << " "); delete fKey; fKey = 0; fIndexKeys.clear(); } //..................................................................... void COMET::IDbiResultSet::BuildLookUpTable() const { // // // Purpose: Build look-up Natural Index -> TableRow. // // Contact: N. West // // Program Notes:- // ============= // // This member function assumes that the sub-class can support // the GetTableRow(...) and GetNumRows methods so take care if // called in the sub-class ctor. // Extended Context serach can produce duplicates. Bool_t duplicatesOK = this->IsExtendedContext(); COMETVerbose( "Building look-uptable. Allow duplicates: " << duplicatesOK << " "); for ( Int_t rowNo = this->GetNumRows()-1; rowNo >= 0; --rowNo ) { const COMET::IDbiTableRow* row = this->GetTableRow(rowNo); UInt_t index = row->GetIndex(rowNo); // Ensure we use this class's GetTableRowByIndex, the method is // virtual but if the subclass has called this method then it must // be the right one to use. [Actually COMET::IDbiResultSetAgg overrides // GetTableRowByIndex, but only to make building lazy]. const COMET::IDbiTableRow* row2 = this->COMET::IDbiResultSet::GetTableRowByIndex(index); COMETVerbose( "Look-up. Row no " << rowNo << " index " << index << " row,row2 " << (void*) row << "," << (void*) row2 << " "); if ( row2 != 0 && row2 != row && ! duplicatesOK ) { std::ostringstream msg; msg << "Duplicated row natural index: " << index << " Found at row " << rowNo << " of table " << this->TableName() << ":-\n index of agg " << row->GetAggregateNo(); if ( row->GetOwner() ) msg << "(SEQNO " << row->GetOwner()->GetValidityRec(row).GetSeqNo() << ")"; msg << " matches agg " << row2->GetAggregateNo(); if ( row2->GetOwner() ) msg << "(SEQNO " << row2->GetOwner()->GetValidityRec(row2).GetSeqNo() << ")"; COMETSevere( msg.str() << " "); } else fIndexKeys[index] = row; } } //..................................................................... Bool_t COMET::IDbiResultSet::CanDelete(const COMET::IDbiResultSet* res) { // // // Purpose: See if suitable for deleting. // // Arguments: // res in A COMET::IDbiResultSet that is currently used. // Optional: default = 0. // If the query would be satisfied apart from the date, then // assume we have moved out of the validity window, never // to return! if ( res && this->CanReuse() && this->GetValidityRec().HasExpired(res->GetValidityRec()) ) this->SetCanReuse(kFALSE); return ! this->GetNumClients() && ! this->CanReuse(); } //..................................................................... void COMET::IDbiResultSet::CaptureExceptionLog(UInt_t startFrom) { // // // Purpose: Capture Exception Log from latest entries in Global Exception Log. fExceptionLog.Clear(); COMET::IDbiExceptionLog::GetGELog().Copy(fExceptionLog,startFrom); } //..................................................................... void COMET::IDbiResultSet::GenerateKey() { // // // Purpose: Create key if set not empty and not already done. if ( fKey || this->GetNumRows() == 0) return; fKey = this->CreateKey(); } //..................................................................... const COMET::IDbiResultKey* COMET::IDbiResultSet::GetKey() const { // Purpose: Get the associated COMET::IDbiResultKey, or an empty one if none exists. return fKey ? fKey : COMET::IDbiResultKey::GetEmptyKey(); } //..................................................................... const COMET::IDbiTableRow* COMET::IDbiResultSet::GetTableRowByIndex(UInt_t index) const { // // // Purpose: Return row corresponding to Natural Index (or 0 if none) // // Contact: N. West // // Use Find rather than operator[] to avoid creating entry // if index missing IndexToRow_t::const_iterator idx = fIndexKeys.find(index); return ( idx == fIndexKeys.end() ) ? 0 : (*idx).second; } //..................................................................... Bool_t COMET::IDbiResultSet::Satisfies(const COMET::IVldContext& vc, const IDbi::Task& task) { // // // Purpose: Check to see if this Result satisfies specific context query. // // Arguments: // vc in Context of query // task in Task of query // // Return: kTRUE if can satisfy query. // // Contact: N. West // // Program Notes:- // ============= // If it cannot satisfy the query in a way that suggests // that its unlikely that it will satisfy future queries // then mark as cannot reuse so that it becomes eligible // for purging. // Extended Context queries cannot satisfy specific context queries. Bool_t isExtendedContext = this->IsExtendedContext(); Bool_t canReuse = this->CanReuse(); Bool_t isCompatible = this->GetValidityRec().IsCompatible(vc,task); Bool_t hasExpired = this->GetValidityRec().HasExpired(vc,task); UInt_t numClients = this->GetNumClients(); COMETDebug( " Checking result with COMET::IDbiValidityRec:- \n " << this->GetValidityRec() << " With extended context: " << isExtendedContext << " CanReuse: " << canReuse << " Is Compatible: " << isCompatible << " HasExpired: " << hasExpired << " number of clients: " << numClients << " "); if ( isExtendedContext ) return kFALSE; if ( canReuse && isCompatible ) return kTRUE; // If the query would be satisfied apart from the date, then // assume we have moved out of the validity window, never // to return! if ( canReuse && hasExpired && numClients == 0 ) { COMETDebug( " Marking result as not reusable" << " "); this-> SetCanReuse(kFALSE); } return kFALSE; } //..................................................................... void COMET::IDbiResultSet::Streamer(COMET::IDbiBinaryFile& file) { // // // Purpose: I/O to binary file // // Program Notes:- // ============= // Don't store fIndexKeys; it will be rebuilt on input by the subclass. if ( file.IsReading() ) { COMETDebug( " Restoring COMET::IDbiResultSet ..." << " "); file >> fCanReuse; fEffVRec.Streamer(file); COMETVerbose( " Restored " << fEffVRec << " "); fResultsFromDb = kFALSE; fNumClients = 0; file >> fTableName; COMETVerbose( " Restored string " << fTableName << " "); } else if ( file.IsWriting() ) { COMETDebug( " Saving COMET::IDbiResultSet ..." << " "); file << fCanReuse; COMETVerbose( " Saving " << fEffVRec << " "); fEffVRec.Streamer(file); COMETVerbose( " Saving string " << fTableName << " "); file << fTableName; } } /* Template for New Member Function //..................................................................... COMET::IDbiResultSet:: { // // // Purpose: // // Arguments: // xxxxxxxxx in yyyyyy // // Return: // // Contact: N. West // // Specification:- // ============= // // o // Program Notes:- // ============= // None. } */