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

DbiDBProxy.cxx

Go to the documentation of this file.
00001 
00005 
00006 
00007 #include <memory>
00008 #include <cassert>
00009 
00010 #include "TCollection.h"
00011 #include "TList.h"
00012 #include "TSQLColumnInfo.h"
00013 #include "TSQLStatement.h"
00014 #include "TSQLServer.h"
00015 #include "TSQLTableInfo.h"
00016 #include "TString.h"
00017 
00018 #include "Conventions/Detector.h"
00019 #include "Conventions/SimFlag.h"
00020 #include "DatabaseInterface/DbiDBProxy.h"
00021 #include "DatabaseInterface/DbiCascader.h"
00022 #include "DatabaseInterface/DbiFieldType.h"
00023 #include "DatabaseInterface/DbiResultSet.h"
00024 #include "DatabaseInterface/DbiServices.h"
00025 #include "DatabaseInterface/DbiString.h"
00026 #include "DatabaseInterface/DbiStatement.h"
00027 #include "DatabaseInterface/DbiTableMetaData.h"
00028 #include "DatabaseInterface/DbiTimerManager.h"
00029 #include "LeakChecker/Lea.h"
00030 #include "MessageService/MsgService.h"
00031 #include "Validity/VldContext.h"
00032 
00033 #include "Util/UtilString.h"
00034 
00035 ClassImp(DbiDBProxy)
00036 
00037 //   Typedefs
00038 //   ********
00039 
00040 //   Definition of static data members
00041 //   *********************************
00042 
00043 CVSID("$Id: DbiDBProxy.cxx,v 1.82 2009/01/30 09:52:57 nwest Exp $");
00044 
00045 //    Definition of all member functions (static or otherwise)
00046 //    *******************************************************
00047 //
00048 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00049 
00050 
00051 //.....................................................................
00052 
00053 DbiDBProxy::DbiDBProxy(DbiCascader& cascader,
00054                        const string& tableName,
00055                        const DbiTableMetaData* metaData,
00056                        const DbiTableMetaData* metaValid,
00057                        const DbiTableProxy* tableProxy) :
00058 fCascader(cascader),
00059 fMetaData(metaData),
00060 fMetaValid(metaValid),
00061 fTableName(tableName),
00062 fTableNameUc(UtilString::ToUpper(tableName)),
00063 fTableProxy(tableProxy),
00064 fVldSuffix("VLD")
00065 {
00066 //
00067 //
00068 //  Purpose:  Constructor
00069 //
00070 //  Arguments:   
00071 //  cascader   in   Reference to one and only cascader
00072 //  tableName  in   Table name.
00073 //  metaData   in   Meta data for main table.
00074 //  metaValid  in   Meta data for validity.
00075 //  tableProxy in   Owning DbiTableProxy.
00076 //
00077 
00078   LEA_CTOR    //Leak Checker
00079     
00080 // If table name in mixed case, then use old suffix.
00081   if ( fTableName != fTableNameUc ) fVldSuffix = "Validity";
00082 
00083 }
00084 
00085 //.....................................................................
00086 
00087 DbiDBProxy::~DbiDBProxy() {
00088 //
00089 //
00090 //  Purpose: Destructor
00091 
00092   LEA_DTOR    //Leak Checker
00093 
00094   MSG("Dbi", Msg::kVerbose) << "Destroying DbiDBProxy " 
00095                           << fTableName << " at " << this
00096                           << endl;
00097 
00098 }
00099 //.....................................................................
00100 
00101 void DbiDBProxy::FindTimeBoundaries(const VldContext& vc, 
00102                                     const Dbi::Task& task,
00103                                     UInt_t dbNo,
00104                                     VldTimeStamp earliestCreate,
00105                                     VldTimeStamp& start,
00106                                     VldTimeStamp& end) const {
00107 //
00108 //
00109 //  Purpose: Find next time boundaries beyond standard time gate. 
00110 //
00111 //  Arguments: 
00112 //    vc             in    The Validity Context for the query.
00113 //    task           in    The task of the query.
00114 //    dbNo           in    Database number in cascade (starting at 0).
00115 //    earliestCreate in    Earliest creation date of data in the time gate
00116 //    start          out   Lower time boundary or VldTimeStamp(0,0) if none
00117 //    end            out   Upper time boundary or VldTimeStamp(0x7FFFFFFF,0) if none
00118 //
00119 //  Specification:-
00120 //  =============
00121 //
00122 //  o Find the next time boundary (either TIMESTART or TIMEEND)
00123 //    outside the current time gate with a creation date >= earliestCreate.
00124 
00125   MSG("Dbi",Msg::kSynopsis) << "FindTimeBoundaries for table " <<  fTableName
00126                             << " context " << vc 
00127                             << " task " << task 
00128                             << " Earliest creation date " <<  earliestCreate
00129                             << " database " << dbNo << endl;
00130 
00131 //  Set the limits wide open
00132   start = VldTimeStamp(0,0);
00133   end   = VldTimeStamp(0x7FFFFFFF,0);
00134  
00135 //  Construct a Time Gate on the current date.
00136 
00137   const VldTimeStamp curVTS = vc.GetTimeStamp();
00138   Int_t timeGate = Dbi::GetTimeGate(this->GetTableName());
00139   time_t vcSec = curVTS.GetSec() - timeGate;
00140   VldTimeStamp startGate(vcSec,0);
00141   vcSec += 2*timeGate;
00142   VldTimeStamp endGate(vcSec,0);
00143   string earliestCreateString(Dbi::MakeDateTimeString(earliestCreate));
00144   string startGateString(Dbi::MakeDateTimeString(startGate));
00145   string endGateString(Dbi::MakeDateTimeString(endGate));
00146 
00147 // Extract information for VldContext.
00148 
00149   Detector::Detector_t    detType(vc.GetDetector());
00150   SimFlag::SimFlag_t       simFlg(vc.GetSimFlag());
00151 
00152 // Use an auto_ptr to manage ownership of DbiStatement and TSQLStatement
00153   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
00154 
00155   for (int i_limit =1; i_limit <= 4; ++i_limit ) {
00156     DbiString sql("select ");
00157     if ( i_limit == 1 ) sql  << "min(TIMESTART) from " << fTableName
00158                              << "VLD where TIMESTART > '" << endGateString << "' ";
00159     if ( i_limit == 2 ) sql  << "min(TIMEEND) from " << fTableName
00160                              << "VLD where TIMEEND > '" << endGateString  << "' ";
00161     if ( i_limit == 3 ) sql  << "max(TIMESTART) from " << fTableName
00162                              << "VLD where TIMESTART < '" << startGateString << "' ";
00163     if ( i_limit == 4 ) sql  << "max(TIMEEND) from " << fTableName
00164                              << "VLD where TIMEEND < '" << startGateString  << "' ";
00165     sql << " and DetectorMask & " << static_cast<unsigned int>(detType) 
00166         << " and SimMask & " << static_cast<unsigned int>(simFlg)
00167         << " and CREATIONDATE >= '" << earliestCreateString << "'"
00168         << " and  Task = " << task;
00169     MSG("Dbi",Msg::kSynopsis) << "  FindTimeBoundaries query no. " << i_limit 
00170                           << " SQL:" <<sql.c_str() << endl;
00171 
00172     auto_ptr<TSQLStatement> stmt(stmtDb->ExecuteQuery(sql.c_str()));
00173     stmtDb->PrintExceptions(Msg::kDebug);
00174 
00175 //  If the query returns data, convert to a time stamp and trim the limits
00176     TString date;
00177     if ( ! stmt.get() || ! stmt->NextResultRow() || stmt->IsNull(0) ) continue;
00178     date = stmt->GetString(0);
00179     if ( date.IsNull() ) continue;
00180     VldTimeStamp ts(Dbi::MakeTimeStamp(date.Data()));
00181     MSG("Dbi",Msg::kSynopsis) << "  FindTimeBoundaries query result: " << ts << endl;
00182     if ( i_limit <= 2 && ts < end   ) end   = ts;
00183     if ( i_limit >= 3 && ts > start ) start = ts;
00184 
00185   }
00186 
00187   MSG("Dbi",Msg::kSynopsis) << "FindTimeBoundaries for table " <<  fTableName
00188                         << " found " << start << " .. " << end << endl;
00189 
00190 }
00191 //.....................................................................
00192 
00193 UInt_t DbiDBProxy::GetNumDb() const {
00194 //
00195 //
00196 //  Purpose:  Return the number of databases in the cascade.
00197 
00198   return fCascader.GetNumDb();
00199 
00200 }
00201 
00202 //.....................................................................
00203 
00204 DbiResultSet*  DbiDBProxy::QueryAllValidities (UInt_t dbNo,UInt_t seqNo) const {
00205 //
00206 //
00207 //  Purpose:  Apply all validities query to database..
00208 //
00209 //  Arguments: 
00210 //    dbNo         in    Database number in cascade (starting at 0).
00211 //    seqNo        in    Just this SEQNO if >0 or all if 0 [default: 0]
00212 //
00213 //  Return:    New DbiResult object.
00214 //             NB  Caller is responsible for deleting..
00215 //
00216 //  Contact:   N. West
00217 //
00218 //  Specification:-
00219 //  =============
00220 //
00221 //  o Ask for every row in associated validity range table and return 
00222 //    query results qualifying selection by fSqlCondition if defined.
00223 
00224 //  Program Notes:-
00225 //  =============
00226 
00227 //  This function is provided to support database maintenance
00228 //  rather than standard Dbi related I/O
00229 
00230 
00231 // Generate SQL for validity table.
00232 
00233   DbiString sql;
00234 
00235   sql << "select * from " << fTableName << fVldSuffix;
00236   if ( fSqlCondition != "" ) sql << " where " << fSqlCondition;
00237   if ( seqNo > 0 ) {
00238     if ( fSqlCondition == "" ) sql << " where ";
00239     else                       sql << " and ";         
00240     sql << "seqno = " << seqNo;
00241   }
00242   sql  << ";" << '\0';
00243 
00244   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00245                          << " query: " << sql.GetString() << endl;
00246 
00247 //  Apply query and return result..
00248 
00249   DbiStatement* stmtDb = fCascader.CreateStatement(dbNo);
00250   return new DbiResultSet(stmtDb,sql,fMetaValid,fTableProxy,dbNo);
00251 
00252 }
00253 
00254 
00255 
00256 //.....................................................................
00257 
00258 DbiResultSet*  DbiDBProxy::QuerySeqNo(UInt_t seqNo, UInt_t dbNo) const {
00259 //
00260 //
00261 //  Purpose:  Apply sequence query to database..
00262 //
00263 //  Arguments: 
00264 //    seqNo        in    The sequence number for the query.
00265 //    dbNo         in    Database number in cascade (starting at 0).
00266 //
00267 //  Return:    New DbiResult object.
00268 //             NB  Caller is responsible for deleting..
00269 //
00270 //  Contact:   N. West
00271 //
00272 //  Specification:-
00273 //  =============
00274 //
00275 //  o Apply sequence query to table and return query results
00276 
00277 //  Program Notes:-
00278 //  =============
00279 
00280 //  None..
00281 
00282 // Generate SQL.
00283 
00284   DbiTimerManager::gTimerManager.RecMainQuery();
00285   DbiString sql;
00286   sql << "select * from " << fTableName << " where " 
00287       << "    SEQNO= " << seqNo;
00288 
00289   if ( DbiServices::OrderContextQuery() && fMetaData->HasRowCounter() )
00290     sql << " order by ROW_COUNTER";
00291 
00292   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00293                          << " SeqNo query: " << sql.c_str() << endl;
00294   
00295 //  Apply query and return result..
00296 
00297   DbiStatement* stmtDb = fCascader.CreateStatement(dbNo);
00298   return new DbiResultSet(stmtDb,sql,fMetaData,fTableProxy,dbNo);
00299 
00300 }
00301 
00302 //.....................................................................
00303 
00304 DbiResultSet*  DbiDBProxy::QuerySeqNos(SeqList_t& seqNos,
00305                                        UInt_t dbNo,
00306                                        const string& sqlData,
00307                                        const string& fillOpts) const {
00308 //
00309 //
00310 //  Purpose:  Apply query for a list of sequence numbers to database..
00311 //
00312 //  Arguments: 
00313 //    seqNos       in    The vector of sequence numbers for the query.
00314 //                       Should be in acsending order, see Program Notes
00315 //    dbNo         in    Database number in cascade (starting at 0).
00316 //    sqlData      in    Optional SQL extension to secondary query.
00317 //    fillOpts     in    Optional fill options (available to DbiTableRow
00318 //                       objects when filling.
00319 //
00320 //  Return:    New DbiResult object.
00321 //             NB  Caller is responsible for deleting..
00322 //
00323 //  Contact:   N. West
00324 //
00325 //  Specification:-
00326 //  =============
00327 //
00328 //  o Apply sequence query to table and return query results
00329 
00330 //  Program Notes:-
00331 //  =============
00332 
00333 //  Where possible the SQL query is kept to a minimm by using
00334 //  `BETWEEN' comparison to bracket ranges of numbers.
00335 
00336 // Generate SQL.
00337 
00338   if ( seqNos.size() == 0 ) return 0;
00339 
00340   DbiTimerManager::gTimerManager.RecMainQuery();
00341   DbiString sql;
00342   sql << "select * from " << fTableName << " where ";
00343 
00344   if ( sqlData != "" ) sql << "( ";
00345   Bool_t first = kTRUE;
00346   SeqList_t::const_iterator itr1 = seqNos.begin();
00347 
00348   while ( itr1 != seqNos.end() ) {
00349     UInt_t seq1 = *itr1;
00350     UInt_t seq2 = seq1;
00351     SeqList_t::const_iterator itr2 = itr1;
00352     while ( itr2 != seqNos.end() && seq2 == *itr2 ) {
00353       ++itr2;
00354       ++seq2;
00355     }
00356     if ( first ) {
00357       first = kFALSE;
00358     }
00359     else {      
00360       sql << "or ";
00361     }
00362     if ( seq2 > seq1 + 1) {
00363       sql << "SEQNO between " << seq1 << " and " << seq2-1 << ' ';
00364       itr1 = itr2;
00365     }
00366     else {
00367       sql << "SEQNO = " << seq1 << ' ';
00368       ++itr1;
00369     }
00370   }
00371     
00372   if ( sqlData != "" ) sql << ")  and " << "(" << sqlData << ")" << " ";
00373 
00374   sql << "order by SEQNO";
00375 
00376   if ( DbiServices::OrderContextQuery() && fMetaData->HasRowCounter() )
00377     sql << ",ROW_COUNTER";
00378 
00379   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00380                          << " SeqNos query: " << sql.c_str() << endl;
00381   
00382 //  Apply query and return result..
00383 
00384   DbiStatement* stmtDb = fCascader.CreateStatement(dbNo);
00385   return new DbiResultSet(stmtDb,sql,fMetaData,fTableProxy,dbNo,fillOpts);
00386 
00387 }
00388 
00389 //.....................................................................
00390 
00391 DbiResultSet*  DbiDBProxy::QueryValidity (const VldContext& vc,
00392                                           const Dbi::Task& task,
00393                                           UInt_t dbNo) const {
00394 //
00395 //
00396 //  Purpose:  Apply validity query to database..
00397 //
00398 //  Arguments: 
00399 //    vc           in    The Validity Context for the query.
00400 //    task         in    The task of the query.
00401 //    dbNo         in    Database number in cascade (starting at 0).
00402 //
00403 //  Return:    New DbiResult object.
00404 //             NB  Caller is responsible for deleting..
00405 //
00406 //  Contact:   N. West
00407 //
00408 //  Specification:-
00409 //  =============
00410 //
00411 //  o Apply query to associated validity range table and return query
00412 //    results qualifying selection by fSqlCondition if defined.
00413 
00414 //  Program Notes:-
00415 //  =============
00416 
00417 //  Rather than search over the full table this function places
00418 //  a time gate round the context time and then trims any validity
00419 //  range returned to this gate.  See FindTimeBoundaries to get a
00420 //  more accurate validity range.
00421 
00422 //  Construct a search window on the current date.
00423 
00424   const VldTimeStamp curVTS = vc.GetTimeStamp();
00425   Int_t timeGate = Dbi::GetTimeGate(this->GetTableName());
00426   time_t vcSec = curVTS.GetSec() - timeGate;
00427   VldTimeStamp startGate(vcSec,0);
00428   vcSec += 2*timeGate;
00429   VldTimeStamp endGate(vcSec,0);
00430 
00431 // Extract information for VldContext.
00432 
00433   string startGateString(Dbi::MakeDateTimeString(startGate));
00434   string endGateString(Dbi::MakeDateTimeString(endGate));
00435   Detector::Detector_t    detType(vc.GetDetector());
00436   SimFlag::SimFlag_t       simFlg(vc.GetSimFlag());
00437 
00438 // Generate SQL for context.
00439 
00440   DbiString context;
00441   context << "    TimeStart <= '" << endGateString << "' "
00442           << "and TimeEnd    > '" << startGateString << "' "
00443           << "and DetectorMask & " << static_cast<unsigned int>(detType) 
00444           << " and SimMask & " << static_cast<unsigned int>(simFlg);
00445 
00446 //  Apply query and return result..
00447 
00448   return this->QueryValidity(context.GetString(),task,dbNo);
00449 
00450 }
00451 //.....................................................................
00452 
00453 DbiResultSet*  DbiDBProxy::QueryValidity (const string& context, 
00454                                           const Dbi::Task& task,
00455                                           UInt_t dbNo) const {
00456 //
00457 //
00458 //  Purpose:  Apply validity query to database..
00459 //
00460 //  Arguments: 
00461 //    context      in    The Validity Context (see DbiSqlContext)
00462 //    task         in    The task of the query.
00463 //    dbNo         in    Database number in cascade (starting at 0).
00464 //
00465 //  Return:    New DbiResult object.
00466 //             NB  Caller is responsible for deleting..
00467 //
00468 //  Contact:   N. West
00469 //
00470 //  Specification:-
00471 //  =============
00472 //
00473 //  o Apply query to associated validity range table and return query
00474 //    results qualifying selection by fSqlCondition if defined.
00475 
00476 
00477 // Generate SQL for validity table.
00478 
00479   DbiString sql;
00480 
00481 // Queries are normally ordered by creation date (the later the better)
00482 // but make an exception for DBUSUBRUNSUMMARY which has open-ended
00483 // end date and an unreliable creation date so the latest start date is 
00484 // best.
00485 // Same for DBURUNSUMMARY.  Bogus entries with wrong validity are stomping 
00486 // real values for the same reason.  These should be cleaned +up in the DB 
00487 // but TIMESTART should be always more valid than CREATIONDATE for such info
00488   string orderByName("CREATIONDATE");
00489   if ((fTableName == "DBUSUBRUNSUMMARY") || (fTableName == "DBURUNSUMMARY"))
00490       orderByName = "TIMESTART";
00491   sql << "select * from " << fTableName << fVldSuffix 
00492       << " where " ;
00493   if ( fSqlCondition != "" 
00494       ) sql << fSqlCondition << " and ";
00495   sql << context;
00496   if ( task != Dbi::kAnyTask
00497        ) sql << " and  Task = " << task
00498              << " order by " << orderByName << " desc;" << '\0';
00499 
00500   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00501                          << " query: " << sql.c_str() << endl;
00502 
00503 //  Apply query and return result..
00504 
00505   DbiStatement* stmtDb = fCascader.CreateStatement(dbNo);
00506   return new DbiResultSet(stmtDb,sql,fMetaValid,fTableProxy,dbNo);
00507 
00508 }
00509 //.....................................................................
00510 
00511 DbiResultSet*  DbiDBProxy::QueryValidity (UInt_t seqNo,
00512                                           UInt_t dbNo) const {
00513 //
00514 //
00515 //  Purpose:  Apply validity query to database..
00516 //
00517 //  Arguments: 
00518 //    seqNo        in    The SEQNO of the validity rec.
00519 //
00520 //  Return:    New DbiResult object.
00521 //             NB  Caller is responsible for deleting..
00522 //
00523 //  Contact:   N. West
00524 //
00525 //  Specification:-
00526 //  =============
00527 //
00528 //  o Apply query to associated validity range table and return query
00529 //    results qualifying selection by fSqlCondition if defined.
00530 
00531 
00532 // Generate SQL for validity table.
00533 
00534   DbiString sql;
00535   sql << "select * from " << fTableName << fVldSuffix << " where ";
00536   if ( fSqlCondition != "" ) sql << fSqlCondition << " and ";
00537   sql << "SEQNO = " << seqNo << ";";
00538 
00539   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00540                          << " SEQNO query: " << sql.c_str() << endl;
00541 
00542 //  Apply query and return result..
00543 
00544   DbiStatement* stmtDb = fCascader.CreateStatement(dbNo);
00545   return new DbiResultSet(stmtDb,sql,fMetaValid,fTableProxy,dbNo);
00546 
00547 }
00548 
00549 //.....................................................................
00550 
00551 Bool_t DbiDBProxy::RemoveSeqNo(UInt_t seqNo,
00552                                UInt_t dbNo) const {
00553 //
00554 //
00555 //  Purpose:  Remove sequence number in main and auxiliary tables.
00556 //
00557 //  Arguments: 
00558 //    seqNo        in    The sequence number to be removed.
00559 //    dbNo         in    Database number in cascade (starting at 0). 
00560 //
00561 //  Return:    kTRUE if output successful,otherwise kFALSE.
00562 //
00563 //  Contact:   N. West
00564 //
00565 //  Specification:-
00566 //  =============
00567 //
00568 //  o Remove sequence number in main and auxiliary tables.
00569 
00570 //  Program Notes:-
00571 //  =============
00572 
00573 //  None.
00574 
00575 
00576 // Generate SQL to remove SeqNo in main table.
00577   DbiString sql;
00578   sql  << "delete from  " << fTableName 
00579        << " where SEQNO = " << seqNo << ";"
00580        << '\0';
00581 
00582   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00583                         << " RemoveSeqNo SQL: " << sql.c_str() << endl;
00584 
00585 //  Apply query.
00586   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
00587   if ( ! stmtDb.get() ) return false;
00588   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00589     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00590                            << " Failed. " << endl;
00591     return false;
00592   }
00593 
00594 // Generate SQL to remove SeqNo in validity table.
00595   sql.GetString().erase();
00596   sql << "delete from  " << fTableName << fVldSuffix
00597       << " where SEQNO = " << seqNo << ";"
00598       << '\0';
00599 
00600   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00601                         << " RemoveSeqNo SQL: " << sql.c_str() << endl;
00602 
00603 //  Apply query.
00604   if (  ! stmtDb->ExecuteUpdate(sql.c_str()) ||  stmtDb->PrintExceptions() ) {
00605     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00606                            << " Failed. " << endl;
00607     return false;
00608   }
00609 
00610   return true;
00611 
00612 }
00613 
00614 //.....................................................................
00615 
00616 Bool_t DbiDBProxy::ReplaceInsertDate(const VldTimeStamp& ts,
00617                                      UInt_t SeqNo,
00618                                      UInt_t dbNo) const{
00619 //
00620 //
00621 //  Purpose:  Replace insertion date for row in auxiliary table.
00622 //
00623 //  Arguments: 
00624 //    ts           in    Time stamp for new insertion date.
00625 //    SeqNo        in    The sequence number of the row to be replaced.
00626 //    dbNo         in    Database number in cascade (starting at 0). 
00627 //
00628 //  Return:    kTRUE if output successful,otherwise kFALSE.
00629 //
00630 //  Contact:   N. West
00631 
00632 
00633 // Generate SQL.
00634   DbiString sql;
00635   sql << "update  " << fTableName << fVldSuffix
00636       << " set INSERTDATE = \'" << ts.AsString("s")
00637       << "\' where SEQNO = " << SeqNo << ";"
00638       << '\0';
00639 
00640   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00641                         << " ReplaceInsertDate SQL: " 
00642                         << sql.c_str() << endl;
00643 
00644 //  Apply query.
00645   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
00646   if ( ! stmtDb.get() ) return false;
00647   if (! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00648     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00649                            << " Failed. " << endl;
00650     return false;
00651   }
00652 
00653   return true;
00654 
00655 }
00656 //.....................................................................
00657 
00658 Bool_t DbiDBProxy::ReplaceSeqNo(UInt_t oldSeqNo,
00659                                 UInt_t newSeqNo,
00660                                 UInt_t dbNo) const {
00661 //
00662 //
00663 //  Purpose:  Replace sequence number in main and auxiliary tables.
00664 //
00665 //  Arguments: 
00666 //    oldSeqNo     in    The old sequence number.
00667 //    nwSeqNo      in    The new sequence number.
00668 //    dbNo         in    Database number in cascade (starting at 0). 
00669 //
00670 //  Return:    kTRUE if output successful,otherwise kFALSE.
00671 //
00672 //  Contact:   N. West
00673 //
00674 //  Specification:-
00675 //  =============
00676 //
00677 //  o Replace sequence number in main and auxiliary tables.
00678 
00679 //  Program Notes:-
00680 //  =============
00681 
00682 //  None.
00683 
00684   if ( ! fCascader.GetConnection(dbNo) ) {
00685     MSG("Dbi",Msg::kWarning)
00686        << "Cannot renumber " << oldSeqNo
00687        << " no connection to cascade entry " << dbNo << endl;
00688     return false;
00689   }
00690 // Deal with Oracle separately - it's best.
00691   if ( fCascader.GetConnection(dbNo)->GetDbType () == Dbi::kOracle )
00692     return this->ReplaceSeqNoOracle(oldSeqNo,newSeqNo,dbNo);
00693 
00694 // Generate SQL to replace SeqNo in validity table.
00695   DbiString sql;
00696   sql << "update  " << fTableName << fVldSuffix
00697       << " set SEQNO = " << newSeqNo 
00698       << " where SEQNO = " << oldSeqNo << ";"
00699       << '\0';
00700 
00701   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00702                         << " ReplaceSeqNo SQL: " << sql.c_str() << endl;
00703 
00704 //  Apply query.
00705   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
00706   if ( ! stmtDb.get() ) return false;
00707   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00708     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00709                            << " Failed. " << endl;
00710     return false;
00711   }
00712 
00713 // Generate SQL to replace SeqNo in main table.
00714   sql.GetString().erase();
00715   sql  << "update  " << fTableName 
00716        << " set SEQNO = " << newSeqNo 
00717        << " where SEQNO = " << oldSeqNo << ";"
00718        << '\0';
00719 
00720   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00721                         << " ReplaceSeqNo SQL: " << sql.c_str() << endl;
00722 
00723 //  Apply query.
00724   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00725     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00726                            << " Failed. " << endl;
00727     return false;
00728   }
00729 
00730   return true;
00731 
00732 }
00733 //.....................................................................
00734 
00735 Bool_t DbiDBProxy::ReplaceSeqNoOracle(UInt_t oldSeqNo,
00736                                       UInt_t newSeqNo,
00737                                       UInt_t dbNo) const {
00738 //
00739 //
00740 //  Purpose:  Replace sequence number in main and auxiliary tables.  Oracle version
00741 //
00742 //  Arguments: 
00743 //    oldSeqNo     in    The old sequence number.
00744 //    nwSeqNo      in    The new sequence number.
00745 //    dbNo         in    Database number in cascade (starting at 0). 
00746 //
00747 //  Return:    kTRUE if output successful,otherwise kFALSE.
00748 //
00749 //  Contact:   N. West
00750 //
00751 //  Specification:-
00752 //  =============
00753 //
00754 //  o Replace sequence number in main and auxiliary tables.
00755 
00756 //  Program Notes:-
00757 //  =============
00758 
00759 //  Constraints between the main and VLD tables means that neither can simple get
00760 //  updated without violating the constraint, so it's necessary to duplicate the
00761 //  VLD entry, move the main entry and finally delete the old entry.
00762 
00763 // Check that old VLD entry exists.
00764 
00765   DbiResultSet* rsOld = QueryValidity(oldSeqNo,dbNo);
00766   if ( rsOld && rsOld->IsBeforeFirst() ) rsOld->FetchRow();
00767   if ( ! rsOld || rsOld->IsExhausted() ) {
00768     MSG("Dbi",Msg::kWarning) << "Cannot renumber " << oldSeqNo
00769                            << " it does not exist" << endl;
00770     delete rsOld;
00771     return false;
00772   }
00773 
00774 // Generate SQL to add new SeqNo in validity vable.
00775 
00776   DbiString sql;
00777   sql << "insert into " << fTableName << fVldSuffix
00778       << " values (" << newSeqNo;
00779 
00780   rsOld->IncrementCurCol();
00781   UInt_t numCols =rsOld->NumCols();
00782   for (UInt_t iCol = 2; iCol <= numCols; ++iCol) {
00783     UInt_t concept = rsOld->CurColFieldType().GetConcept();
00784     string delim = "";
00785     if (    concept == Dbi::kString 
00786          || concept == Dbi::kDate 
00787          || concept == Dbi::kChar ) delim = "\'";  
00788     sql << "," << delim << rsOld->CurColValue() << delim ;
00789     rsOld->IncrementCurCol();
00790   }
00791   sql << ")";   
00792   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00793                         << " ReplaceSeqNo SQL (insert new VLD): " << sql.c_str() << endl;
00794   delete rsOld;
00795 
00796 //  Apply query.
00797   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
00798   if ( ! stmtDb.get() ) return false;
00799   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00800     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00801                            << " Failed. " << endl;
00802     return false;
00803   }
00804 
00805 // Generate SQL to replace SeqNo in main table.
00806   sql.GetString().erase();
00807   sql  << "update  " << fTableName 
00808        << " set SEQNO = " << newSeqNo 
00809        << " where SEQNO = " << oldSeqNo << ";";
00810 
00811   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00812                         << " ReplaceSeqNo SQL (rename main entry): " << sql.c_str() << endl;
00813 
00814 //  Apply query.
00815   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00816     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00817                            << " Failed. " << endl;
00818     return false;
00819   }
00820 
00821 // Generate SQL to remove old SeqNo in validity table.
00822   sql.GetString().erase();
00823   sql  << "delete from  " << fTableName << fVldSuffix
00824        << " where SEQNO = " << oldSeqNo << ";";
00825 
00826   MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00827                         << " ReplaceSeqNo SQL (delete old VLD): " << sql.c_str() << endl;
00828 
00829 //  Apply query.
00830   if ( ! stmtDb->ExecuteUpdate(sql.c_str()) || stmtDb->PrintExceptions() ) {
00831     MAXMSG("Dbi",Msg::kError,20) << "SQL: " << sql.c_str()
00832                            << " Failed. " << endl;
00833     return false;
00834   }
00835 
00836   return true;
00837 
00838 
00839 }
00840 //.....................................................................
00841 
00842 void  DbiDBProxy::StoreMetaData(DbiTableMetaData& metaData) const {
00843 //
00844 //
00845 //  Purpose:  Store table meta data.
00846 //
00847 //  Arguments: 
00848 //    metaData   in    Empty DbiTableMetaData object apart from table name.
00849 
00850 
00851 
00852   const char* tableName = metaData.TableName().c_str(); 
00853   MSG("Dbi",Msg::kSynopsis) << "Get meta-data for table: " << tableName << endl;
00854   
00855 //  Check each Db in turn until table found and store table meta data.
00856 
00857   for ( UInt_t dbNo = 0; dbNo < fCascader.GetNumDb(); dbNo++ ) {
00858     DbiConnection* connection = fCascader.GetConnection(dbNo); 
00859     TSQLServer* server = connection->GetServer();
00860     if ( ! server ) continue;
00861     connection->Connect();
00862     TSQLTableInfo* meta = server->GetTableInfo(tableName);
00863     if ( ! meta ) {
00864       connection->DisConnect();
00865       continue;
00866     }
00867     MSG("Dbi",Msg::kSynopsis) << "Meta-data query succeeded on cascade entry " << dbNo << endl;
00868 
00869     // Clear out any existing data, although there should not be any.
00870     metaData.Clear();
00871 
00872     const TList* cols =  meta->GetColumns();
00873     TIter colItr(cols);
00874     int col = 0;
00875     while ( TSQLColumnInfo* colInfo = dynamic_cast<TSQLColumnInfo*>(colItr.Next()) ) {
00876 
00877       ++col;
00878       string name(colInfo->GetName());
00879       name = UtilString::ToUpper(name);
00880       metaData.SetColName(name,col);
00881 
00882       DbiFieldType fldType(colInfo->GetSQLType(),
00883                            colInfo->GetLength(),
00884                            colInfo->GetTypeName());
00885 
00886       // For now continue to check for unsigned (even though not supported)
00887       if ( !colInfo->IsSigned() ) fldType.SetUnsigned();
00888       metaData.SetColFieldType(fldType,col);
00889 
00890       metaData.SetColIsNullable(col,colInfo->IsNullable());
00891 
00892       MSG("Dbi",Msg::kSynopsis) 
00893            << "Column "         << col << " " << name
00894            << " SQL type "      << colInfo->GetSQLType()
00895            << " SQL type name " << colInfo->GetTypeName()
00896            << " DBI type "      << fldType.AsString() 
00897            << " data size: "    << fldType.GetSize()
00898            << " col size: "     << colInfo->GetLength() << endl;
00899 
00900     }
00901     delete meta;
00902     connection->DisConnect();
00903     return;
00904   }
00905 }
00906 
00907 //.....................................................................
00908 
00909 Bool_t DbiDBProxy::TableExists(Int_t selectDbNo) const {
00910 //
00911 //
00912 //  Purpose:  Return true if table exists on selected cascade entry
00913 //            or any entry if selectDbNo=-1 (default)
00914 
00915 
00916   return fCascader.TableExists(fTableName,selectDbNo);
00917 
00918 }
00919 

Generated on Mon Feb 15 11:06:34 2010 for loon by  doxygen 1.3.9.1