TDbiResultSetAgg.cxx

Go to the documentation of this file.
00001 // $Id: TDbiResultSetAgg.cxx,v 1.2 2011/06/08 09:49:18 finch Exp $
00002 
00003 
00004 #include <algorithm>
00005 #include <map>
00006 #include <vector>
00007 
00008 #include "TDbiCache.hxx"
00009 #include "TDbiBinaryFile.hxx"
00010 #include "TDbiDBProxy.hxx"
00011 #include "TDbiResultSetAgg.hxx"
00012 #include "TDbiResultSetNonAgg.hxx"
00013 #include "TDbiResultKey.hxx"
00014 #include "TDbiInRowStream.hxx"
00015 #include "TDbiTableRow.hxx"
00016 #include "TDbiTimerManager.hxx"
00017 #include "TDbiValidityRecBuilder.hxx"
00018 #include <TSK_DBI_Log.hxx>
00019 #include <MsgFormat.h>
00020 using std::endl;
00021 #include "TVldRange.hxx"
00022 #include "UtilString.hxx"
00023 
00024 ClassImp(TDbiResultSetAgg)
00025 
00026 typedef vector<const TDbiResultSet*>::const_iterator ConstResultItr_t;
00027 
00028 
00029 //   Definition of static data members
00030 //   *********************************
00031 
00032 
00033 
00034 //    Definition of all member functions (static or otherwise)
00035 //    *******************************************************
00036 //
00037 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00038 
00039 //.....................................................................
00040 ///\verbatim
00041 ///
00042 ///  Purpose:  Default constructor
00043 ///
00044 ///  Arguments:
00045 ///      tableName    in     Name of table.
00046 ///      tableRow     in     Pointer to a sample tableRow object.
00047 ///                          May be null.
00048 ///      cache        in/out Pointer to a cache. May be null.
00049 ///      vrecBuilder  in     Pointer to validity record builder containing
00050 ///                          aggregated records from query. May be null
00051 ///      proxy         in    Pointer to database proxy. May be null.
00052 ///      sqlQualifiers in    Extended Context sql qualifiers
00053 ///
00054 ///  Return:    n/a
00055 ///
00056 ///  Contact:   N. West
00057 ///
00058 ///  Specification:-
00059 ///  =============
00060 ///
00061 ///  o Create Result from TDbiInRowStream generated by query.
00062 ///
00063 ///
00064 ///  Program Notes:-
00065 ///  =============
00066 ///
00067 ///  tableRow is just used to create new subclass TDbiTableRow objects.
00068 ///\endverbatim
00069 TDbiResultSetAgg::TDbiResultSetAgg(const string& tableName,
00070                            const TDbiTableRow* tableRow,
00071                            TDbiCache* cache,
00072                            const TDbiValidityRecBuilder* vrecBuilder,
00073                            const TDbiDBProxy* proxy,
00074                            const string& sqlQualifiers) :
00075 TDbiResultSet(0,0,sqlQualifiers),
00076 fSize(0)
00077 {
00078 
00079 
00080   typedef map<UInt_t,UInt_t> seqToRow_t;
00081 
00082   SK_DBI_Trace( "Creating TDbiResultSetAgg" << "  ");
00083   SetTableName(tableName);
00084   if ( ! tableRow || ! cache || ! vrecBuilder || ! proxy ) return;
00085 
00086 // Unpack the extended context SQL qualifiers.
00087 // Don't use StringTok - it eats null strings
00088 // e.g. abc;;def gives 2 substrings.
00089 
00090   string::size_type loc  = sqlQualifiers.find(';');
00091   string::size_type loc2 = sqlQualifiers.find(';',loc+1);
00092   string sqlData  = string(sqlQualifiers,loc+1,loc2-loc-1);
00093   string fillOpts = string(sqlQualifiers,loc2+1);
00094 
00095 //Loop over all rows looking to see if they are already in
00096 //the cache, and if not, recording their associated sequence numbers
00097 
00098   vector<UInt_t> reqSeqNos;  // Sequence numbers required from DB.
00099   seqToRow_t seqToRow;       // Map SeqNo - > RowNo.
00100 //  Set up a Default database number, it will be updated if anything
00101 //  needs to be read from the database.
00102   UInt_t dbNo = 0;
00103   Int_t maxRowNo = vrecBuilder->GetNumValidityRec() - 1;
00104 
00105 //Ignore the first entry from the validity rec builder, it will be
00106 //for Agg No = -1, which should not be present for aggregated data.
00107   for ( Int_t rowNo = 1; rowNo <= maxRowNo; ++rowNo ) {
00108     const TDbiValidityRec& vrecRow = vrecBuilder->GetValidityRec(rowNo);
00109 
00110 //  If its already in the cache, then just connect it in.
00111     const TDbiResultSet* res = cache->Search(vrecRow,sqlQualifiers);
00112     SK_DBI_Verbose( "Checking validity rec " << rowNo
00113                               << " " << vrecRow
00114                               << "SQL qual: " << sqlQualifiers
00115                               << " cache search: " << (void*) res << "  ");
00116     if ( res ) {
00117       fResults.push_back(res);
00118       res->Connect();
00119       fSize += res->GetNumRows();
00120     }
00121 
00122 //  If its not in the cache, but represents a gap, then create an empty
00123 //  TDbiResultSet and add it to the cache.
00124     else if ( vrecRow.IsGap() ) {
00125       TDbiResultSet* newRes = new TDbiResultSetNonAgg(0, tableRow, &vrecRow);
00126       cache->Adopt(newRes,false);
00127       fResults.push_back(newRes);
00128       newRes->Connect();
00129     }
00130 
00131 //  Neither in cache, nor a gap, so record its sequence number.
00132     else {
00133       UInt_t seqNo = vrecRow.GetSeqNo();
00134       reqSeqNos.push_back(seqNo);
00135       seqToRow[seqNo] = rowNo;
00136       fResults.push_back(0);
00137 //    All data must come from a single database, so any vrec will
00138 //    do to define which one.
00139       dbNo = vrecRow.GetDbNo();
00140     }
00141   }
00142 
00143 //If there are required sequence numbers, then read them from the
00144 //database and build TDbiResultSets for each.
00145 
00146   if ( reqSeqNos.size() ) {
00147 //  Sort into ascending order; it may simplify the query which will
00148 //  block ranges of sequence numbers together.
00149     sort(reqSeqNos.begin(),reqSeqNos.end());
00150     TDbiInRowStream* rs = proxy->QuerySeqNos(reqSeqNos,dbNo,sqlData,fillOpts);
00151 //  Flag that data was read from Database.
00152     this->SetResultsFromDb();
00153     TDbiTimerManager::gTimerManager.StartSubWatch(1);
00154     while ( ! rs->IsExhausted() ) {
00155       Int_t seqNo;
00156       *rs >> seqNo;
00157       rs->DecrementCurCol();
00158       Int_t rowNo = -2;
00159       if ( seqToRow.find(seqNo) == seqToRow.end() ) {
00160         SK_DBI_Severe(  "Unexpected SeqNo: " << seqNo << "  ");
00161       }
00162       else {
00163         rowNo = seqToRow[seqNo];
00164         SK_DBI_Verbose(  "Procesing SeqNo: " << seqNo
00165           << " for row " << rowNo << "  ");
00166       }
00167 
00168       const TDbiValidityRec& vrecRow = vrecBuilder->GetValidityRec(rowNo);
00169       TDbiResultSetNonAgg* newRes = new TDbiResultSetNonAgg(rs,tableRow,&vrecRow);
00170 //    Don't allow results from Extended Context queries to be reused.
00171       if ( this->IsExtendedContext() ) newRes->SetCanReuse(false);
00172       if ( rowNo == -2 ) {
00173         delete newRes;
00174       }
00175       else {
00176         SK_DBI_Verbose(  "SeqNo: " << seqNo
00177           << " produced " << newRes->GetNumRows() << " rows" << "  ");
00178 //      Adopt but don't register key for this component, only the overall TDbiResultSetAgg
00179 //      will have a registered key.
00180         cache->Adopt(newRes,false);
00181         fResults[rowNo-1] = newRes;
00182         newRes->Connect();
00183         fSize += newRes->GetNumRows();
00184       }
00185     }
00186 
00187 //  TDbiInRowStream fully processed, so delete it.
00188     delete rs;
00189   }
00190 
00191 //All component TDbiResultSetNonAgg objects have now been located and
00192 //connected in, so set up their access keys and determine the validty
00193 //range by ANDing the time windows together.
00194 
00195   fRowKeys.reserve(fSize);
00196 
00197   TDbiValidityRec vRec = vrecBuilder->GetValidityRec(1);
00198   for ( Int_t rowNo = 1; rowNo <= maxRowNo; ++rowNo ) {
00199 
00200     const TDbiValidityRec& vrecRow = vrecBuilder->GetValidityRec(rowNo);
00201     TVldRange r = vrecRow.GetVldRange();
00202     vRec.AndTimeWindow(r.GetTimeStart(),r.GetTimeEnd());
00203 
00204     const TDbiResultSet* res = fResults[rowNo-1];
00205     if ( res ) {
00206       UInt_t numEnt = res->GetNumRows();
00207       for (UInt_t entNo = 0; entNo < numEnt; ++entNo )
00208          fRowKeys.push_back(res->GetTableRow(entNo));
00209     }
00210   }
00211 
00212 // Now that the row look-up table has been built the natural index
00213 // look-up table can be filled in.
00214   this->BuildLookUpTable();
00215 
00216 // Set aggregate number to -1 to show that it has multiple aggregates
00217   vRec.SetAggregateNo(-1);
00218   SetValidityRec(vRec);
00219 
00220   SK_DBI_Debug(  "Aggregate contains " << fSize  << " entries.  vRec:-" << "  "
00221     << vRec << "  ");
00222 
00223    SK_DBI_Info( "Created aggregated result set no. of rows: "
00224                              << this->GetNumRows() << "  ");
00225 
00226 }
00227 
00228 //.....................................................................
00229 ///\verbatim
00230 ///
00231 ///  Purpose: Destructor
00232 ///
00233 ///  Arguments:
00234 ///    None.
00235 ///
00236 ///  Return:    n/a
00237 ///
00238 ///  Contact:   N. West
00239 ///
00240 ///  Specification:-
00241 ///  =============
00242 ///
00243 ///  o  Destroy ResultAgg and disconnect all associated TDbiResultSets,
00244 ///\endverbatim
00245 TDbiResultSetAgg::~TDbiResultSetAgg() {
00246 
00247 
00248 //  Program Notes:-
00249 //  =============
00250 
00251 //  None.
00252 
00253 
00254   SK_DBI_Trace( "Destroying TDbiResultSetAgg."  << "  ");
00255 
00256   for ( ConstResultItr_t itr = fResults.begin();
00257         itr != fResults.end();
00258         ++itr) if ( *itr ) (*itr)->Disconnect();
00259 
00260 }
00261 //.....................................................................
00262 
00263 ///
00264 ///  Purpose:  Create a key that corresponds to this result.
00265 ///            Caller must take ownership.
00266 ///
00267 TDbiResultKey* TDbiResultSetAgg::CreateKey() const {
00268 
00269   TDbiResultKey* key = 0;
00270   for ( ConstResultItr_t itr = fResults.begin();
00271         itr != fResults.end();
00272         ++itr ) {
00273     const TDbiResultSet* result = *itr;
00274     if ( result ) {
00275       // Create key from first result.
00276       if ( ! key ) key = result->CreateKey();
00277       // Extend key from the remainder.
00278       else {
00279         const TDbiValidityRec& vrec = result->GetValidityRec();
00280         key->AddVRecKey(vrec.GetSeqNo(),vrec.GetCreationDate());
00281       }
00282     }
00283   }
00284 
00285 // Should not have an empty set, but just in case.
00286   if ( ! key ) key = new TDbiResultKey();
00287 
00288   return key;
00289 
00290 }
00291 //.....................................................................
00292 ///\verbatim
00293 ///
00294 ///  Purpose:  Return TableRow from last query.
00295 ///
00296 ///  Arguments:
00297 ///    row         in    Required row.
00298 ///
00299 ///  Return:    TableRow ptr, or =0 if no row.
00300 ///\endverbatim
00301 const TDbiTableRow* TDbiResultSetAgg::GetTableRow(UInt_t row) const {
00302 
00303 //  Contact:   N. West
00304 
00305 //  Program Notes:-
00306 //  =============
00307 
00308 //  None.
00309 
00310   return  ( row >= fRowKeys.size() ) ? 0 : fRowKeys[row];
00311 
00312 }
00313 
00314 //.....................................................................
00315 ///\verbatim
00316 ///
00317 ///  Purpose:  Get TDbiValidityRec associated with table or row.
00318 ///
00319 ///  Arguments:
00320 ///    row          in    The table row
00321 ///                       or null (default) to get table TDbiValidityRec
00322 ///  Program Notes:-
00323 ///  =============
00324 ///
00325 ///  The TDbiValidityRec for the in-memory table is effectively an
00326 ///  AND of the TDbiValidityRecs of the individual rows.
00327 ///
00328 ///\endverbatim
00329 const TDbiValidityRec& TDbiResultSetAgg::GetValidityRec(
00330                                   const TDbiTableRow* row) const {
00331 
00332 //  Contact:   N. West
00333 //
00334 
00335 
00336  if ( ! row ) return this->GetValidityRecGlobal();
00337  TDbiResultSet* owner = row->GetOwner();
00338  return owner ? owner->GetValidityRecGlobal() : this->GetValidityRecGlobal();
00339 
00340 }
00341 //.....................................................................
00342 ///  Purpose:  Return true if result satisfies extended context query.
00343 Bool_t TDbiResultSetAgg::Satisfies(const string& sqlQualifiers)  {
00344 //
00345 //
00346 
00347 //
00348 
00349   SK_DBI_Debug(  "Trying to satisfy: SQL: " << sqlQualifiers
00350     << "\n with CanReuse: " << this->CanReuse()
00351     << " sqlQualifiers: " << this->GetSqlQualifiers()
00352     << "  ");
00353  return    this->CanReuse()
00354         && this->GetSqlQualifiers() == sqlQualifiers;
00355 }
00356 
00357 //.....................................................................
00358 ///
00359 ///
00360 ///  Purpose:  I/O to binary file
00361 ///
00362 void TDbiResultSetAgg::Streamer(TDbiBinaryFile& bf) {
00363 
00364 //  Specification:-
00365 //  =============
00366 
00367 //  Output constituent non-gap TDbiResultSetNonAgg objects.
00368 
00369   vector<const TDbiResultSet*>::const_iterator itr = fResults.begin();
00370   vector<const TDbiResultSet*>::const_iterator end = fResults.end();
00371 
00372   UInt_t numNonAgg = 0;
00373   for (; itr != end; ++itr) {
00374     const TDbiResultSetNonAgg* rna = dynamic_cast<const TDbiResultSetNonAgg*>(*itr);
00375     if ( rna && ! rna->GetValidityRecGlobal().IsGap() ) ++numNonAgg;
00376   }
00377   bf << numNonAgg;
00378 
00379 
00380   for (itr = fResults.begin(); itr != end; ++itr) {
00381     const TDbiResultSetNonAgg* rna = dynamic_cast<const TDbiResultSetNonAgg*>(*itr);
00382     if ( rna && ! rna->GetValidityRecGlobal().IsGap() ) bf << *rna;
00383   }
00384 }
00385 
00386 /*    Template for New Member Function
00387 
00388 //.....................................................................
00389 
00390 TDbiResultSetAgg:: {
00391 //
00392 //
00393 //  Purpose:
00394 //
00395 //  Arguments:
00396 //    xxxxxxxxx    in    yyyyyy
00397 //
00398 //  Return:
00399 //
00400 //  Contact:   N. West
00401 //
00402 //  Specification:-
00403 //  =============
00404 //
00405 //  o
00406 
00407 //  Program Notes:-
00408 //  =============
00409 
00410 //  None.
00411 
00412 
00413 }
00414 
00415 */
00416 
00417 

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1