00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <Riostream.h>
00021 #include <vector>
00022 #include <map>
00023 #include <stdlib.h>
00024
00025 #include "TString.h"
00026 #include "TROOT.h"
00027 #include "TSystem.h"
00028 #include "TError.h"
00029 #include "TFile.h"
00030 #include "TTree.h"
00031 #include "TLeaf.h"
00032 #include "TBranch.h"
00033
00034 #include "TSQLRow.h"
00035 #include "TSQLResult.h"
00036 #include "TSQLServer.h"
00037
00038 #include "TTreeSQL.h"
00039 #include "TBasketSQL.h"
00040
00041 ClassImp(TTreeSQL)
00042
00043
00044 TTreeSQL::TTreeSQL(TSQLServer *server, TString DB, const TString& table) :
00045 TTree(table.Data(), "Database read from table: " + table, 0), fDB(DB),
00046 fTable(table.Data()),
00047 fResult(0), fRow(0),
00048 fServer(server),
00049 fBranchChecked(kFALSE)
00050 {
00051
00052
00053 fCurrentEntry = -1;
00054 fQuery = TString("Select * from " + fTable);
00055 fEntries = 0;
00056
00057 if (fServer==0) {
00058 Error("TTreeSQL","No TSQLServer specified");
00059 return;
00060 }
00061 if (CheckTable(fTable.Data())) {
00062 Init();
00063 }
00064 }
00065
00066
00067 TBranch* TTreeSQL::BranchImp(const char *, const char *,
00068 TClass *, void *, Int_t ,
00069 Int_t )
00070 {
00071
00072
00073 Fatal("BranchImp","Not implemented yet");
00074 return 0;
00075 }
00076
00077
00078 TBranch* TTreeSQL::BranchImp(const char *, TClass *,
00079 void *, Int_t , Int_t )
00080 {
00081
00082
00083 Fatal("BranchImp","Not implemented yet");
00084 return 0;
00085 }
00086
00087
00088 Int_t TTreeSQL::Branch(TCollection *, Int_t,
00089 Int_t, const char *)
00090 {
00091
00092
00093 Fatal("Branch","Not implemented yet");
00094 return 0;
00095 }
00096
00097
00098 Int_t TTreeSQL::Branch(TList *, Int_t, Int_t)
00099 {
00100
00101
00102 Fatal("Branch","Not implemented yet");
00103 return 0;
00104 }
00105
00106
00107 Int_t TTreeSQL::Branch(const char *, Int_t ,
00108 Int_t)
00109 {
00110
00111
00112 Fatal("Branch","Not implemented yet");
00113 return 0;
00114 }
00115
00116
00117 TBranch* TTreeSQL::Bronch(const char *, const char *, void *,
00118 Int_t, Int_t)
00119 {
00120
00121
00122 Fatal("Bronc","Not implemented yet");
00123 return 0;
00124 }
00125
00126
00127 TBranch* TTreeSQL::BranchOld(const char *, const char *,
00128 void *, Int_t, Int_t)
00129 {
00130
00131
00132 Fatal("BranchOld","Not implemented yet");
00133 return 0;
00134 }
00135
00136
00137 TBranch *TTreeSQL::Branch(const char *, const char *, void *,
00138 Int_t, Int_t)
00139 {
00140
00141
00142 Fatal("Branch","Not implemented yet");
00143 return 0;
00144 }
00145
00146
00147 TBranch * TTreeSQL::Branch(const char *name, void *address,
00148 const char *leaflist, Int_t bufsize)
00149 {
00150
00151
00152 Int_t nb = fBranches.GetEntriesFast();
00153 TBranch *branch;
00154 TString brName;
00155
00156 for (int i=0;i<nb;i++) {
00157 branch = (TBranch*)fBranches.UncheckedAt(i);
00158 brName = branch->GetName();
00159 if (brName.Index(name) == 0) {
00160
00161
00162
00163
00164
00165 Fatal("Branch()", "Duplicate branch!!!");
00166
00167
00168
00169
00170
00171
00172 }
00173 }
00174 return TTree::Branch(name, address, leaflist, bufsize);
00175 }
00176
00177
00178 void TTreeSQL::CheckBasket(TBranch *branch)
00179 {
00180
00181
00182 TBasketSQL* basket = (TBasketSQL *)branch->GetBasket(0);
00183
00184 if (basket==0) {
00185 basket = (TBasketSQL*)CreateBasket(branch);
00186 if (basket==0) return;
00187
00188 branch->GetListOfBaskets()->AddAtAndExpand(basket,0);
00189 }
00190 TBuffer * buffer = basket->GetBufferRef();
00191
00192 if(buffer == 0){
00193 vector<Int_t> *columns = GetColumnIndice(branch);
00194 if (columns) basket->CreateBuffer(branch->GetName(),"A", columns, branch, &fResult);
00195 }
00196
00197 Int_t nb = branch->GetListOfBranches()->GetEntriesFast();
00198 for (int i=0;i<nb;i++) {
00199 TBranch * subbranch = (TBranch*)branch->GetListOfBranches()->UncheckedAt(i);
00200 if(subbranch) CheckBasket(subbranch);
00201 }
00202 }
00203
00204
00205 Bool_t TTreeSQL::CheckBranch(TBranch * tb)
00206 {
00207
00208
00209
00210 if (fServer==0) {
00211 return kFALSE;
00212 }
00213 TString leafName;
00214 TLeaf *leaf;
00215 Int_t nl;
00216 TString str = "";
00217 TString typeName = "";
00218
00219 if (!tb) return kFALSE;
00220
00221 TBasketSQL *basket = (TBasketSQL *)tb->GetBasket(0);
00222 if (!basket) return kFALSE;
00223
00224 TSQLResult *rs = basket->GetResultSet();
00225 if (!rs) {
00226 Error("CheckBranch","%s has basket but no resultset yet",tb->GetName());
00227 return kFALSE;
00228 }
00229
00230 nl = tb->GetNleaves();
00231
00232 for(int j=0;j<nl;j++) {
00233 leaf = (TLeaf*)tb->GetListOfLeaves()->UncheckedAt(j);
00234 typeName = leaf->GetTypeName();
00235 typeName = ConvertTypeName(leaf->GetTypeName());
00236 leafName = leaf->GetName();
00237 str = "";
00238 str = tb->GetName();
00239 str += "__";
00240 str += leafName;
00241
00242 for (int i=0; i< rs->GetFieldCount(); ++i) {
00243 if (str.CompareTo(rs->GetFieldName(i),TString::kIgnoreCase) == 0) return kTRUE;
00244 }
00245
00246
00247
00248 CreateBranch(str, typeName);
00249 }
00250 return kFALSE;
00251 }
00252
00253
00254 Bool_t TTreeSQL::CheckTable(const TString &table) const
00255 {
00256
00257
00258 if (fServer==0) return kFALSE;
00259 TSQLResult * tables = fServer->GetTables(fDB.Data(),table);
00260 TSQLRow * row = 0;
00261 while( (row = tables->Next()) ) {
00262 if(table.CompareTo(row->GetField(0),TString::kIgnoreCase)==0){
00263 return kTRUE;
00264 }
00265 }
00266
00267 Int_t before = gErrorIgnoreLevel;
00268 gErrorIgnoreLevel = kFatal;
00269 TSQLResult *res = fServer->GetColumns(fDB.Data(),table);
00270 if (res) {
00271 delete res;
00272 return kTRUE;
00273 }
00274 gErrorIgnoreLevel = before;
00275
00276 return kFALSE;
00277 }
00278
00279
00280 TString TTreeSQL::ConvertTypeName(const TString& typeName )
00281 {
00282
00283
00284 TString tn = "";
00285
00286 if(typeName == "Char_t"){
00287 tn = "TEXT";
00288 }
00289 else if(typeName == "Int_t") {
00290 tn = "INTEGER";
00291 }
00292 else if(typeName == "Short_t") {
00293 tn = "SMALLINT";
00294 }
00295 else if( typeName == "UShort_t") {
00296 tn = "SMALLINT UNSIGNED";
00297 }
00298 else if(typeName == "Float_t"){
00299 tn = "FLOAT";
00300 }
00301 else if(typeName == "Float16_t"){
00302 tn = "FLOAT";
00303 }
00304 else if(typeName == "Double_t"){
00305 tn = "DOUBLE";
00306 }
00307 else if(typeName == "Double32_t"){
00308 tn = "FLOAT";
00309 }
00310 else if(typeName == "UInt_t") {
00311 tn = "INT UNSIGNED";
00312 }
00313 else if( typeName == "Long_t") {
00314 tn = "INTEGER";
00315 }
00316 else if( typeName == "ULong_t") {
00317 tn = "INTEGER UNSIGNED";
00318 }
00319 else if( typeName == "Long64_t") {
00320 tn = "BIGINT";
00321 }
00322 else if( typeName == "ULong64_t") {
00323 tn = "BIGINT UNSIGNED";
00324 }
00325 else if( typeName == "Bool_t") {
00326 tn = "BOOL";
00327 }
00328 else {
00329 Error("ConvertTypeName","TypeName (%s) not found",typeName.Data());
00330 return "";
00331 }
00332
00333 return tn;
00334 }
00335
00336
00337 TBasket * TTreeSQL::CreateBasket(TBranch * tb)
00338 {
00339
00340
00341 if (fServer==0) {
00342 Error("CreateBasket","No TSQLServer specified");
00343 return 0;
00344 }
00345 vector<Int_t> *columnVec = GetColumnIndice(tb);
00346 if (columnVec) {
00347 return new TBasketSQL(tb->GetName(), tb->GetName(), tb,
00348 &fResult, &fInsertQuery, columnVec, &fRow);
00349 } else {
00350 return 0;
00351 }
00352 }
00353
00354
00355 void TTreeSQL::CreateBranch(const TString &branchName, const TString &typeName)
00356 {
00357
00358
00359 if (fServer==0) {
00360 Error("CreateBranch","No TSQLServer specified");
00361 return;
00362 }
00363 TString alterSQL = "";
00364 alterSQL = "";
00365 alterSQL = "ALTER TABLE ";
00366 alterSQL += fTable.Data();
00367 alterSQL += " ADD ";
00368 alterSQL += branchName.Data();;
00369 alterSQL += " ";
00370 alterSQL += typeName;
00371 alterSQL += " ";
00372
00373 fServer->Query(alterSQL);
00374 }
00375
00376
00377 TString TTreeSQL::CreateBranches(TSQLResult * rs)
00378 {
00379
00380
00381 if(!rs) return "";
00382
00383 Int_t rows;
00384 TString type;
00385 TString res;
00386 TString branchName;
00387 TString leafName;
00388 Int_t prec=0;
00389 TBranch * br = 0;
00390 rows = rs->GetRowCount();
00391 TString decl;
00392 TString prevBranch;
00393
00394 for( int i=0; i < rows; ++i ) {
00395 TSQLRow * row = rs->Next();
00396 type = row->GetField(1);
00397 Int_t index = type.First('(');
00398 if(index>0){
00399 prec = atoi(type(index+1,type.First(')')-1).Data());
00400 type = type(0,index);
00401 }
00402 branchName = row->GetField(0);
00403 Int_t pos;
00404 if ((pos=branchName.Index("__"))!=kNPOS) {
00405 leafName = branchName(pos+2,branchName.Length());
00406 branchName.Remove(pos);
00407 } else {
00408 leafName = branchName;
00409 }
00410 if (prevBranch.Length()) {
00411 if (prevBranch != branchName) {
00412
00413 if (decl.Length()) decl.Remove(decl.Length()-1);
00414 br = TTree::Branch(prevBranch,0,decl);
00415 br->ResetAddress();
00416
00417 (br->GetBasketEntry())[0] = 0;
00418 (br->GetBasketEntry())[1] = fEntries;
00419
00420 br->SetEntries(fEntries);
00421
00422
00423 br->GetListOfBaskets()->AddAtAndExpand(CreateBasket(br),0);
00424
00425 prevBranch = branchName;
00426 decl = "";
00427 }
00428 } else {
00429 prevBranch = branchName;
00430 }
00431
00432 if(type.CompareTo("varchar",TString::kIgnoreCase)==0 || type.CompareTo("varchar2",TString::kIgnoreCase)==0 || type.CompareTo("char",TString::kIgnoreCase)==0 ) {
00433 char siz[6];
00434 snprintf(siz,6,"[%d]",prec);
00435 decl.Append( leafName+siz+"/C:" );
00436 }
00437 else if(type.CompareTo("int",TString::kIgnoreCase)==0){
00438 decl.Append( leafName+"/I:" );
00439 }
00440 else if( type.CompareTo("date",TString::kIgnoreCase)==0 ||
00441 type.CompareTo("time",TString::kIgnoreCase)==0 ||
00442 type.CompareTo("timestamp",TString::kIgnoreCase)==0 ) {
00443 decl.Append( leafName+"/I:" );
00444 }
00445 else if(type.CompareTo("bit",TString::kIgnoreCase)==0 ||
00446 type.CompareTo("tinyint",TString::kIgnoreCase)==0 ||
00447 type.CompareTo("smallint",TString::kIgnoreCase)==0 ) {
00448 decl.Append( leafName+"/i:" );
00449 }
00450 else if(type.CompareTo("real",TString::kIgnoreCase)==0 || type.CompareTo("longvarchar",TString::kIgnoreCase)==0 || type.CompareTo("longvarbinary",TString::kIgnoreCase)==0 || type.CompareTo("varbinary",TString::kIgnoreCase)==0 ){
00451 decl.Append( leafName+"/S:" );
00452 }
00453
00454
00455
00456
00457
00458 else
00459 {
00460
00461 decl.Append( leafName+"/F:" );
00462 }
00463
00464 }
00465
00466
00467 if (decl.Length()) decl.Remove(decl.Length()-1);
00468 if (prevBranch.Length()) {
00469 br = TTree::Branch(prevBranch,0,decl);
00470 br->ResetAddress();
00471
00472 (br->GetBasketEntry())[0] = 0;
00473 (br->GetBasketEntry())[1] = fEntries;
00474 br->SetEntries(fEntries);
00475 br->GetListOfBaskets()->AddAtAndExpand(CreateBasket(br),0);
00476 }
00477
00478 if(!res.IsNull()) res.Resize(res.Length()-1);
00479 return res;
00480 }
00481
00482
00483 Bool_t TTreeSQL::CreateTable(const TString &table)
00484 {
00485
00486
00487 if (fServer==0) {
00488 Error("CreateTable","No TSQLServer specified");
00489 return false;
00490 }
00491 Int_t i, j;
00492 Int_t length;
00493 TString branchName, leafName, typeName;
00494 TString createSQL, alterSQL, str;
00495 Int_t nb = fBranches.GetEntriesFast();
00496 Int_t nl = 0;
00497
00498 TBranch *branch;
00499 TLeaf *leaf;
00500
00501 for (i=0;i<nb;i++) {
00502 branch = (TBranch*)fBranches.UncheckedAt(i);
00503 branchName = branch->GetName();
00504 nl = branch->GetNleaves();
00505 for(j=0;j<nl;j++) {
00506 leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
00507 leafName = leaf->GetName();
00508 typeName = ConvertTypeName(leaf->GetTypeName());
00509 length = leaf->GetLenStatic();
00510
00511 if(i == 0 && j == 0) {
00512 createSQL = "";
00513 createSQL += "CREATE TABLE ";
00514 createSQL += table;
00515 createSQL += " (";
00516 createSQL += branchName;
00517 createSQL += "__";
00518 createSQL += leafName;
00519 createSQL += " ";
00520 createSQL += typeName;
00521 createSQL += " ";
00522 createSQL += ")";
00523
00524 TSQLResult *sres = fServer->Query(createSQL.Data());
00525 if (!sres) {
00526 Error("CreateTable","May have failed");
00527 return false;
00528 }
00529 }
00530 else {
00531 str = "";
00532 str = branchName;
00533 str += "__";
00534 str += leafName;
00535 CreateBranch(str, typeName);
00536 }
00537 }
00538 }
00539
00540 delete fResult;
00541 fResult = fServer->Query(fQuery.Data());
00542 return (fResult!=0);
00543 }
00544
00545
00546 void TTreeSQL::Init()
00547 {
00548
00549
00550 fCurrentEntry = -1;
00551
00552 GetEntries();
00553
00554 delete fResult;
00555 fResult = fServer->Query(fQuery.Data());
00556 if(!fResult) return;
00557
00558 CreateBranches(fServer->GetColumns(fDB,fTable));
00559 }
00560
00561
00562 Int_t TTreeSQL::Fill()
00563 {
00564
00565
00566 Int_t nb = fBranches.GetEntriesFast();
00567 TString typeName;
00568 TBranch *branch;
00569
00570 if (fServer==0) return 0;
00571
00572 if(!CheckTable(fTable.Data())) {
00573 if (!CreateTable(fTable.Data())) {
00574 return -1;
00575 }
00576 }
00577
00578 PrepEntry(fEntries);
00579
00580 for (int i=0;i<nb;i++) {
00581 branch = (TBranch*)fBranches.UncheckedAt(i);
00582 CheckBasket(branch);
00583 }
00584
00585 if (!fBranchChecked) {
00586 for(int i=0;i<nb;i++) {
00587 branch = (TBranch*)fBranches.UncheckedAt(i);
00588 if (!CheckBranch(branch)) {
00589 Error("Fill","CheckBranch for %s failed",branch->GetName());
00590 }
00591 }
00592 fBranchChecked = kTRUE;
00593 }
00594 ResetQuery();
00595
00596 TTree::Fill();
00597
00598 if (fInsertQuery[fInsertQuery.Length()-1]!='(') {
00599 fInsertQuery.Remove(fInsertQuery.Length()-1);
00600 fInsertQuery += ")";
00601 TSQLResult *res = fServer?fServer->Query(fInsertQuery):0;
00602
00603 if (res) {
00604 return res->GetRowCount();
00605 }
00606 }
00607 return -1;
00608 }
00609
00610
00611 vector<Int_t> *TTreeSQL::GetColumnIndice(TBranch *branch)
00612 {
00613
00614
00615
00616
00617
00618 if (!CheckTable(fTable)) return 0;
00619
00620 vector<Int_t> *columns = new vector<Int_t>;
00621
00622 Int_t nl = branch->GetNleaves();
00623
00624 vector<TString> names;
00625
00626 TSQLResult *rs = fServer->GetColumns(fDB,fTable);
00627 if (rs==0) { delete columns; return 0; }
00628 Int_t rows = rs->GetRowCount();
00629
00630 pair<TString,Int_t> value;
00631
00632 for (Int_t i=0;i<rows;++i) {
00633 TSQLRow *row = rs->Next();
00634 names.push_back( row->GetField(0) );
00635 delete row;
00636 }
00637 delete rs;
00638
00639 for(int j=0;j<nl;j++) {
00640
00641 Int_t col = -1;
00642 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(j);
00643 TString leafName = leaf->GetName();
00644 TString str;
00645
00646 str = "";
00647 str = branch->GetName();
00648 str += "__";
00649 str += leafName;
00650 for (Int_t i=0;i<rows;++i) {
00651 if (str.CompareTo(names[i],TString::kIgnoreCase)==0) {
00652 col = i;
00653 break;
00654 }
00655 }
00656 if (col<0) {
00657 str = leafName;
00658 for (Int_t i=0;i<rows;++i) {
00659 if (str.CompareTo(names[i],TString::kIgnoreCase)==0) {
00660 col = i;
00661 break;
00662 }
00663 }
00664 }
00665 if(col>=0){
00666 columns->push_back(col);
00667 } else Error("GetColumnIndice","Error finding column %d %s",j,str.Data());
00668 }
00669 if (columns->empty()) {
00670 delete columns; return 0;
00671 } else
00672 return columns;
00673 }
00674
00675
00676 Long64_t TTreeSQL::GetEntries() const
00677 {
00678
00679
00680 if (fServer==0) return GetEntriesFast();
00681 if (!CheckTable(fTable.Data())) return 0;
00682
00683 TTreeSQL* thisvar = (TTreeSQL*)this;
00684
00685
00686
00687
00688 TString counting = "select count(*) from " + fTable;
00689 TSQLResult *count = fServer->Query(counting);
00690
00691 if (count==0) {
00692 thisvar->fEntries = 0;
00693 } else {
00694 TString val = count->Next()->GetField(0);
00695 Long_t ret;
00696 sscanf(val.Data(), "%ld",&(ret) );
00697 thisvar->fEntries = ret;
00698 }
00699 return fEntries;
00700 }
00701
00702
00703 Long64_t TTreeSQL::GetEntriesFast() const
00704 {
00705
00706
00707
00708 return fEntries;
00709 }
00710
00711
00712 Int_t TTreeSQL::GetEntry(Long64_t entry, Int_t getall)
00713 {
00714
00715
00716 if (PrepEntry(entry)>=0) return TTree::GetEntry(entry,getall);
00717 else return -1;
00718 }
00719
00720
00721 Long64_t TTreeSQL::LoadTree(Long64_t entry)
00722 {
00723
00724
00725 fReadEntry = entry;
00726 return PrepEntry(entry);
00727 }
00728
00729
00730 Long64_t TTreeSQL::PrepEntry(Long64_t entry)
00731 {
00732
00733
00734 if (entry < 0 || entry >= fEntries || fServer==0) return 0;
00735 fReadEntry = entry;
00736
00737 if(entry == fCurrentEntry) return entry;
00738
00739 if(entry < fCurrentEntry || fResult==0){
00740 delete fResult;
00741 fResult = fServer->Query(fQuery.Data());
00742 fCurrentEntry = -1;
00743 }
00744
00745 Bool_t reset = false;
00746 while ( fCurrentEntry < entry ) {
00747 ++fCurrentEntry;
00748 delete fRow;
00749 fRow = fResult->Next();
00750 if (fRow==0 && !reset) {
00751 delete fResult;
00752 fResult = fServer->Query(fQuery.Data());
00753 fCurrentEntry = -1;
00754 reset = true;
00755 }
00756 }
00757 if (fRow==0) return -1;
00758 return entry;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 void TTreeSQL::Refresh()
00777 {
00778
00779
00780
00781
00782
00783
00784 GetEntries();
00785 fCurrentEntry = -1;
00786 delete fResult; fResult = 0;
00787 delete fRow; fRow = 0;
00788 }
00789
00790
00791 void TTreeSQL::ResetQuery()
00792 {
00793
00794
00795 fInsertQuery = "INSERT INTO " + fTable + " VALUES (";
00796 }
00797
00798