00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 #include "TSQLFile.h"
00168
00169 #include "TROOT.h"
00170 #include "TSystem.h"
00171 #include "TList.h"
00172 #include "TBrowser.h"
00173 #include "TObjArray.h"
00174 #include "TObjString.h"
00175 #include "TList.h"
00176 #include "TArrayC.h"
00177 #include "TVirtualStreamerInfo.h"
00178 #include "TStreamerElement.h"
00179 #include "TProcessID.h"
00180 #include "TError.h"
00181 #include "TClass.h"
00182
00183 #include "TSQLServer.h"
00184 #include "TSQLTableInfo.h"
00185 #include "TSQLColumnInfo.h"
00186 #include "TSQLStatement.h"
00187 #include "TSQLResult.h"
00188 #include "TSQLRow.h"
00189 #include "TBufferSQL2.h"
00190 #include "TSQLStructure.h"
00191 #include "TKeySQL.h"
00192 #include "TSQLClassInfo.h"
00193 #include "TSQLObjectData.h"
00194
00195 #include "Riostream.h"
00196
00197 ClassImp(TSQLFile);
00198
00199 const char* mysql_BasicTypes[21] = {
00200 "VARCHAR(255)",
00201 "TINYINT UNSIGNED",
00202 "SMALLINT",
00203 "INT",
00204 "BIGINT",
00205 "FLOAT",
00206 "INT",
00207 "VARCHAR(255)",
00208 "DOUBLE",
00209 "DOUBLE",
00210 "",
00211 "TINYINT UNSIGNED",
00212 "SMALLINT UNSIGNED",
00213 "INT UNSIGNED",
00214 "BIGINT UNSIGNED",
00215 "INT UNSIGNED",
00216 "BIGINT",
00217 "BIGINT UNSIGNED",
00218 "BOOL",
00219 "DOUBLE",
00220 ""
00221 };
00222
00223 const char* mysql_OtherTypes[13] = {
00224 "VARCHAR(255)",
00225 "255",
00226 "TEXT",
00227 "DATETIME",
00228 "`",
00229 "dir:id",
00230 "key:id",
00231 "obj:id",
00232 "raw:id",
00233 "str:id",
00234 ":",
00235 "\"",
00236 "InnoDB"
00237 };
00238
00239 const char* oracle_BasicTypes[21] = {
00240 "VARCHAR(255)",
00241 "INT",
00242 "INT",
00243 "INT",
00244 "INT",
00245 "FLOAT",
00246 "INT",
00247 "VARCHAR(255)",
00248 "DOUBLE PRECISION",
00249 "DOUBLE PRECISION",
00250 "",
00251 "INT",
00252 "INT",
00253 "INT",
00254 "INT",
00255 "INT",
00256 "INT",
00257 "INT",
00258 "INT",
00259 "FLOAT",
00260 ""
00261 };
00262
00263 const char* oracle_OtherTypes[13] = {
00264 "VARCHAR(1000)",
00265 "1000",
00266 "VARCHAR(4000)",
00267 "VARCHAR(50)",
00268 "\"",
00269 "dir:id",
00270 "key:id",
00271 "obj:id",
00272 "raw:id",
00273 "str:id",
00274 ":",
00275 "'",
00276 ""
00277 };
00278
00279
00280
00281 TSQLFile::TSQLFile() :
00282 TFile(),
00283 fSQL(0),
00284 fSQLClassInfos(0),
00285 fUseSuffixes(kTRUE),
00286 fSQLIOversion(1),
00287 fArrayLimit(21),
00288 fCanChangeConfig(kFALSE),
00289 fTablesType(),
00290 fUseTransactions(0),
00291 fUseIndexes(0),
00292 fModifyCounter(0),
00293 fQuerisCounter(0),
00294 fBasicTypes(0),
00295 fOtherTypes(0),
00296 fUserName(),
00297 fLogFile(0),
00298 fIdsTableExists(kFALSE),
00299 fStmtCounter(0)
00300 {
00301
00302 SetBit(kBinaryFile, kFALSE);
00303 }
00304
00305
00306 TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const char* pass) :
00307 TFile(),
00308 fSQL(0),
00309 fSQLClassInfos(0),
00310 fUseSuffixes(kTRUE),
00311 fSQLIOversion(1),
00312 fArrayLimit(21),
00313 fCanChangeConfig(kFALSE),
00314 fTablesType(),
00315 fUseTransactions(0),
00316 fUseIndexes(0),
00317 fModifyCounter(0),
00318 fQuerisCounter(0),
00319 fBasicTypes(mysql_BasicTypes),
00320 fOtherTypes(mysql_OtherTypes),
00321 fUserName(user),
00322 fLogFile(0),
00323 fIdsTableExists(kFALSE),
00324 fStmtCounter(0)
00325 {
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if (!gROOT)
00348 ::Fatal("TFile::TFile", "ROOT system not initialized");
00349
00350 gDirectory = 0;
00351 SetName(dbname);
00352 SetTitle("TFile interface to SQL DB");
00353 TDirectoryFile::Build();
00354 fFile = this;
00355
00356 if (dbname && strstr(dbname,"oracle://")!=0) {
00357 fBasicTypes = oracle_BasicTypes;
00358 fOtherTypes = oracle_OtherTypes;
00359 }
00360
00361 fArrayLimit = 21;
00362 fTablesType = SQLDefaultTableType();
00363 fUseIndexes = 1;
00364 fUseTransactions = kTransactionsAuto;
00365
00366 fD = -1;
00367 fFile = this;
00368 fFree = 0;
00369 fVersion = gROOT->GetVersionInt();
00370 fUnits = 4;
00371 fOption = option;
00372 SetCompressionLevel(5);
00373 fWritten = 0;
00374 fSumBuffer = 0;
00375 fSum2Buffer = 0;
00376 fBytesRead = 0;
00377 fBytesWrite = 0;
00378 fClassIndex = 0;
00379 fSeekInfo = 0;
00380 fNbytesInfo = 0;
00381 fProcessIDs = 0;
00382 fNProcessIDs= 0;
00383 fSeekDir = sqlio::Ids_RootDir;
00384 SetBit(kBinaryFile, kFALSE);
00385
00386 fOption = option;
00387 fOption.ToUpper();
00388
00389 if (fOption == "NEW") fOption = "CREATE";
00390
00391 Bool_t breaklock = kFALSE;
00392
00393 if (fOption == "BREAKLOCK") { breaklock = kTRUE; fOption = "UPDATE"; }
00394
00395 Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
00396 Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
00397 Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
00398 Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
00399
00400 if (!create && !recreate && !update && !read) {
00401 read = kTRUE;
00402 fOption = "READ";
00403 }
00404
00405 if (!dbname || !strlen(dbname)) {
00406 Error("TSQLFile", "Database not specified");
00407 goto zombie;
00408 }
00409
00410 gROOT->cd();
00411
00412 fSQL = TSQLServer::Connect(dbname, user, pass);
00413
00414 if (fSQL==0) {
00415 Error("TSQLFile", "Cannot connect to DB %s", dbname);
00416 goto zombie;
00417 }
00418
00419 if (recreate) {
00420 if (IsTablesExists())
00421 if (!IsWriteAccess()) {
00422 Error("TSQLFile", "no write permission, DB %s locked", dbname);
00423 goto zombie;
00424 }
00425 SQLDeleteAllTables();
00426 recreate = kFALSE;
00427 create = kTRUE;
00428 fOption = "CREATE";
00429 }
00430
00431 if (create && IsTablesExists()) {
00432 Error("TSQLFile", "DB tables already exists");
00433 goto zombie;
00434 }
00435
00436 if (update) {
00437 if (!IsTablesExists()) {
00438 update = kFALSE;
00439 create = kTRUE;
00440 }
00441
00442 if (update && !breaklock && !IsWriteAccess()) {
00443 Error("TSQLFile", "no write permission, DB %s locked", dbname);
00444 goto zombie;
00445 }
00446 }
00447
00448 if (read) {
00449 if (!IsTablesExists()) {
00450 Error("TSQLFile", "DB %s tables not exist", dbname);
00451 goto zombie;
00452 }
00453 if (!IsReadAccess()) {
00454 Error("TSQLFile", "no read permission for DB %s tables", dbname);
00455 goto zombie;
00456 }
00457 }
00458
00459 fRealName = dbname;
00460
00461 if (create || update) {
00462 SetWritable(kTRUE);
00463 if (update) SetLocking(kLockBusy);
00464 } else
00465 SetWritable(kFALSE);
00466
00467
00468
00469
00470 fCanChangeConfig = create;
00471
00472 InitSqlDatabase(create);
00473
00474 return;
00475
00476 zombie:
00477
00478 delete fSQL;
00479 fSQL = 0;
00480 MakeZombie();
00481 gDirectory = gROOT;
00482 }
00483
00484
00485 void TSQLFile::StartLogFile(const char* fname)
00486 {
00487
00488
00489 StopLogFile();
00490 fLogFile = new std::ofstream(fname);
00491 }
00492
00493
00494 void TSQLFile::StopLogFile()
00495 {
00496
00497 if (fLogFile!=0) {
00498 delete fLogFile;
00499 fLogFile = 0;
00500 }
00501 }
00502
00503
00504 Bool_t TSQLFile::IsMySQL() const
00505 {
00506
00507 if (fSQL==0) return kFALSE;
00508 return strcmp(fSQL->ClassName(),"TMySQLServer")==0;
00509 }
00510
00511
00512 Bool_t TSQLFile::IsOracle() const
00513 {
00514
00515
00516 if (fSQL==0) return kFALSE;
00517 return strcmp(fSQL->ClassName(),"TOracleServer")==0;
00518 }
00519
00520
00521 Bool_t TSQLFile::IsODBC() const
00522 {
00523
00524
00525 if (fSQL==0) return kFALSE;
00526 return strcmp(fSQL->ClassName(),"TODBCServer")==0;
00527
00528 }
00529
00530
00531 void TSQLFile::SetUseSuffixes(Bool_t on)
00532 {
00533
00534
00535
00536 if (!fCanChangeConfig)
00537 Error("SetUseSuffixes", "Configurations already cannot be changed");
00538 else
00539 fUseSuffixes = on;
00540 }
00541
00542
00543 void TSQLFile::SetArrayLimit(Int_t limit)
00544 {
00545
00546
00547
00548
00549
00550
00551
00552 if (!fCanChangeConfig)
00553 Error("SetArrayLimit", "Configurations already cannot be changed");
00554 else
00555 fArrayLimit = limit;
00556 }
00557
00558
00559 void TSQLFile::SetTablesType(const char* tables_type)
00560 {
00561
00562
00563
00564
00565
00566 if (!fCanChangeConfig)
00567 Error("SetTablesType", "Configurations already cannot be changed");
00568 else
00569 fTablesType = tables_type;
00570 }
00571
00572
00573 void TSQLFile::SetUseTransactions(Int_t mode)
00574 {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 fUseTransactions = mode;
00585 }
00586
00587
00588 Bool_t TSQLFile::StartTransaction()
00589 {
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 if (GetUseTransactions()!=kTransactionsUser) {
00601 Error("SQLStartTransaction","Only allowed when SetUseTransactions(kUserTransactions) was configured");
00602 return kFALSE;
00603 }
00604
00605 return SQLStartTransaction();
00606 }
00607
00608
00609 Bool_t TSQLFile::Commit()
00610 {
00611
00612
00613
00614 if (GetUseTransactions()!=kTransactionsUser) {
00615 Error("SQLCommit","Only allowed when SetUseTransactions(kUserTransactions) was configured");
00616 return kFALSE;
00617 }
00618
00619 return SQLCommit();
00620 }
00621
00622
00623 Bool_t TSQLFile::Rollback()
00624 {
00625
00626
00627
00628 if (GetUseTransactions()!=kTransactionsUser) {
00629 Error("SQLRollback","Only allowed when SetUseTransactions(kUserTransactions) was configured");
00630 return kFALSE;
00631 }
00632
00633 return SQLRollback();
00634 }
00635
00636
00637 void TSQLFile::SetUseIndexes(Int_t use_type)
00638 {
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 if (!fCanChangeConfig)
00649 Error("SetUseIndexes", "Configurations already cannot be changed");
00650 else
00651 fUseIndexes = use_type;
00652 }
00653
00654
00655 const char* TSQLFile::GetDataBaseName() const
00656 {
00657
00658
00659
00660 if (IsOracle()) return 0;
00661 const char* name = strrchr(GetName(),'/');
00662 if (name==0) return 0;
00663 return name + 1;
00664 }
00665
00666
00667 void TSQLFile::Close(Option_t *option)
00668 {
00669
00670
00671
00672 if (!IsOpen()) return;
00673
00674 TString opt = option;
00675 if (opt.Length()>0)
00676 opt.ToLower();
00677
00678 if (IsWritable()) {
00679 SaveToDatabase();
00680 SetLocking(kLockFree);
00681 }
00682
00683 fWritable = kFALSE;
00684
00685 if (fClassIndex) {
00686 delete fClassIndex;
00687 fClassIndex = 0;
00688 }
00689
00690 TDirectory *cursav = gDirectory;
00691 cd();
00692
00693 if (cursav == this || cursav->GetFile() == this) {
00694 cursav = 0;
00695 }
00696
00697
00698 TDirectoryFile::Close();
00699 cd();
00700
00701 if (cursav)
00702 cursav->cd();
00703 else {
00704 gFile = 0;
00705 gDirectory = gROOT;
00706 }
00707
00708
00709 TList pidDeleted;
00710 TIter next(fProcessIDs);
00711 TProcessID *pid;
00712 while ((pid = (TProcessID*)next())) {
00713 if (!pid->DecrementCount()) {
00714 if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid);
00715 } else if(opt.Contains("r")) {
00716 pid->Clear();
00717 }
00718 }
00719 pidDeleted.Delete();
00720
00721 gROOT->GetListOfFiles()->Remove(this);
00722 }
00723
00724
00725 TSQLFile::~TSQLFile()
00726 {
00727
00728
00729 Close();
00730
00731 if (fSQLClassInfos!=0) {
00732 fSQLClassInfos->Delete();
00733 delete fSQLClassInfos;
00734 }
00735
00736 StopLogFile();
00737
00738 if (fSQL!=0) {
00739 delete fSQL;
00740 fSQL = 0;
00741 }
00742 }
00743
00744
00745 void TSQLFile::operator=(const TSQLFile &)
00746 {
00747
00748 }
00749
00750
00751 Bool_t TSQLFile::IsOpen() const
00752 {
00753
00754
00755 return fSQL != 0;
00756 }
00757
00758
00759 Int_t TSQLFile::ReOpen(Option_t* mode)
00760 {
00761
00762
00763
00764 cd();
00765
00766 TString opt = mode;
00767 opt.ToUpper();
00768
00769 if (opt != "READ" && opt != "UPDATE") {
00770 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
00771 return 1;
00772 }
00773
00774 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
00775 return 1;
00776
00777 if (opt == "READ") {
00778
00779
00780 if (IsOpen() && IsWritable()) {
00781 SaveToDatabase();
00782 SetLocking(kLockFree);
00783 }
00784 fOption = opt;
00785
00786 SetWritable(kFALSE);
00787
00788 } else {
00789
00790
00791 if (!IsWriteAccess()) {
00792 Error("ReOpen","Tables are locked, no write access");
00793 return 1;
00794 }
00795
00796 fOption = opt;
00797
00798 SetWritable(kTRUE);
00799
00800 SetLocking(kLockBusy);
00801 }
00802
00803 return 0;
00804 }
00805
00806
00807 TKey* TSQLFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t )
00808 {
00809
00810 return new TKeySQL(mother, obj, name);
00811 }
00812
00813
00814 TKey* TSQLFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t )
00815 {
00816
00817 return new TKeySQL(mother, obj, cl, name);
00818 }
00819
00820
00821 void TSQLFile::WriteHeader()
00822 {
00823
00824
00825 WriteSpecialObject(sqlio::Ids_TSQLFile, this, GetName(), GetTitle());
00826 }
00827
00828
00829 void TSQLFile::WriteStreamerInfo()
00830 {
00831
00832
00833
00834
00835
00836 if (!IsTablesExists()) return;
00837
00838 if (gDebug>1)
00839 Info("WriteStreamerInfo","Saving streamer infos to database");
00840
00841 TList list;
00842
00843 TIter iter(gROOT->GetListOfStreamerInfo());
00844
00845 TVirtualStreamerInfo* info = 0;
00846
00847 while ((info = (TVirtualStreamerInfo*) iter()) !=0 ) {
00848 Int_t uid = info->GetNumber();
00849 if (fClassIndex->fArray[uid]) {
00850 if (gDebug>1) Info("WriteStreamerInfo","Add %s",info->GetName());
00851 list.Add(info);
00852 }
00853 }
00854 if (list.GetSize()==0) return;
00855 fClassIndex->fArray[0] = 2;
00856
00857 WriteSpecialObject(sqlio::Ids_StreamerInfos, &list, "StreamerInfo", "StreamerInfos of this file");
00858
00859 fClassIndex->fArray[0] = 0;
00860 }
00861
00862
00863 Bool_t TSQLFile::WriteSpecialObject(Long64_t keyid, TObject* obj, const char* name, const char* title)
00864 {
00865
00866
00867
00868
00869 DeleteKeyFromDB(keyid);
00870 if (obj==0) return kTRUE;
00871
00872 Long64_t objid = StoreObjectInTables(keyid, obj, obj->IsA());
00873
00874 if (objid>0) {
00875 TDatime now;
00876
00877 TKeySQL* key = new TKeySQL(this, keyid, objid,
00878 name, title,
00879 now.AsSQLString(), 1, obj->ClassName());
00880 WriteKeyData(key);
00881 delete key;
00882 }
00883
00884 return (objid>0);
00885 }
00886
00887
00888 TObject* TSQLFile::ReadSpecialObject(Long64_t keyid, TObject* obj)
00889 {
00890
00891
00892 TKeySQL* key = 0;
00893
00894 StreamKeysForDirectory(this, kFALSE, keyid, &key);
00895 if (key==0) return obj;
00896
00897 TBufferSQL2 buffer(TBuffer::kRead, this);
00898
00899 TClass* cl = 0;
00900
00901 void* res = buffer.SqlReadAny(key->GetDBKeyId(), key->GetDBObjId(), &cl, obj);
00902
00903 if ((cl==TSQLFile::Class()) && (res!=0) && (obj==this)) {
00904
00905 SetTitle(key->GetTitle());
00906 }
00907
00908 delete key;
00909
00910 return (TObject*) res;
00911 }
00912
00913
00914 TList* TSQLFile::GetStreamerInfoList()
00915 {
00916
00917
00918
00919
00920
00921
00922 if (gDebug>1)
00923 Info("GetStreamerInfoList","Start reading of streamer infos");
00924
00925 TObject* obj = ReadSpecialObject(sqlio::Ids_StreamerInfos);
00926
00927 TList* list = dynamic_cast<TList*> (obj);
00928 if (list==0) { delete obj; list = new TList; }
00929
00930 return list;
00931 }
00932
00933
00934 void TSQLFile::SaveToDatabase()
00935 {
00936
00937
00938
00939 if (fSQL==0) return;
00940
00941 WriteStreamerInfo();
00942 WriteHeader();
00943 }
00944
00945
00946 Int_t TSQLFile::StreamKeysForDirectory(TDirectory* dir, Bool_t doupdate, Long64_t specialkeyid, TKeySQL** specialkey)
00947 {
00948
00949
00950
00951
00952 if (dir==0) return -1;
00953
00954 const char* quote = SQLIdentifierQuote();
00955
00956 Long64_t dirid = dir->GetSeekDir();
00957
00958 TString sqlcmd;
00959 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld",
00960 quote, sqlio::KeysTable, quote,
00961 quote, SQLDirIdColumn(), quote, dirid);
00962 if (specialkeyid>=0) {
00963 TString buf;
00964 buf.Form(" AND %s%s%s=%lld", quote, SQLKeyIdColumn(), quote, specialkeyid);
00965 sqlcmd += buf;
00966 }
00967
00968 TSQLResult* res = SQLQuery(sqlcmd.Data(), 2);
00969
00970 if (res==0) return -1;
00971
00972 Int_t nkeys = 0;
00973
00974 TSQLRow* row = 0;
00975
00976 while ((row = res->Next()) != 0) {
00977 nkeys++;
00978
00979 Long64_t keyid = sqlio::atol64((*row)[0]);
00980
00981 Long64_t objid = sqlio::atol64((*row)[2]);
00982 const char* keyname = (*row)[3];
00983 const char* keytitle = (*row)[4];
00984 const char* keydatime = (*row)[5];
00985 Int_t cycle = atoi((*row)[6]);
00986 const char* classname = (*row)[7];
00987
00988 if (gDebug>4)
00989 cout << " Reading keyid = " << keyid << " name = " << keyname << endl;
00990
00991 if ((keyid>=sqlio::Ids_FirstKey) || (keyid==specialkeyid)) {
00992 if (doupdate) {
00993 TKeySQL* key = FindSQLKey(dir, keyid);
00994
00995 if (key==0) {
00996 Error("StreamKeysForDirectory","Key with id %lld not exist in list", keyid);
00997 nkeys = -1;
00998 } else
00999 if (key->IsKeyModified(keyname, keytitle, keydatime, cycle, classname))
01000 UpdateKeyData(key);
01001
01002 } else {
01003 TKeySQL* key = new TKeySQL(dir, keyid, objid,
01004 keyname, keytitle,
01005 keydatime, cycle, classname);
01006 if (specialkey!=0)
01007 { *specialkey = key; nkeys = 1; }
01008 else
01009 dir->GetListOfKeys()->Add(key);
01010 }
01011 }
01012 delete row;
01013 }
01014
01015 delete res;
01016
01017 if (gDebug>4) {
01018 Info("StreamKeysForDirectory","dir = %s numread = %d",dir->GetName(), nkeys);
01019 dir->GetListOfKeys()->Print("*");
01020 }
01021
01022 return nkeys;
01023 }
01024
01025
01026 void TSQLFile::InitSqlDatabase(Bool_t create)
01027 {
01028
01029
01030
01031 Int_t len = gROOT->GetListOfStreamerInfo()->GetSize()+1;
01032 if (len<5000) len = 5000;
01033 fClassIndex = new TArrayC(len);
01034 fClassIndex->Reset(0);
01035
01036 if (!create) {
01037
01038 Bool_t ok = ReadConfigurations();
01039
01040
01041 if (ok) {
01042 ReadSQLClassInfos();
01043
01044 ReadStreamerInfo();
01045
01046 ok = (ReadSpecialObject(sqlio::Ids_TSQLFile, this) != 0);
01047 }
01048
01049
01050 if (ok)
01051 ok = StreamKeysForDirectory(this, kFALSE)>=0;
01052
01053 if (!ok) {
01054 Error("InitSqlDatabase", "Cannot detect proper tabled in database. Close.");
01055 Close();
01056 delete fSQL;
01057 fSQL = 0;
01058 MakeZombie();
01059 gDirectory = gROOT;
01060 return;
01061 }
01062 }
01063
01064 gROOT->GetListOfFiles()->Add(this);
01065 cd();
01066
01067 fNProcessIDs = 0;
01068 TKey* key = 0;
01069 TIter iter(fKeys);
01070 while ((key = (TKey*)iter())!=0) {
01071 if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
01072 }
01073
01074 fProcessIDs = new TObjArray(fNProcessIDs+1);
01075 }
01076
01077
01078 Bool_t TSQLFile::ReadConfigurations()
01079 {
01080
01081
01082 const char* quote = SQLIdentifierQuote();
01083
01084 TString sqlcmd;
01085 sqlcmd.Form("SELECT * FROM %s%s%s",
01086 quote, sqlio::ConfigTable, quote);
01087 TSQLResult* res = SQLQuery(sqlcmd.Data(), 2);
01088
01089 if (res==0) return kFALSE;
01090
01091
01092 fSQLIOversion = 0;
01093
01094 Int_t lock = 0;
01095
01096 #define ReadIntCfg(name, target) \
01097 if ((field.CompareTo(name, TString::kIgnoreCase)==0)) \
01098 target = value.Atoi(); else
01099
01100 #define ReadBoolCfg(name, target) \
01101 if ((field.CompareTo(name, TString::kIgnoreCase)==0)) \
01102 target = value.CompareTo(sqlio::True, TString::kIgnoreCase)==0; else
01103
01104 #define ReadStrCfg(name, target) \
01105 if ((field.CompareTo(name, TString::kIgnoreCase)==0)) \
01106 target = value; else
01107
01108 TSQLRow* row = 0;
01109
01110 while ((row = res->Next()) != 0) {
01111
01112 TString field = row->GetField(0);
01113 TString value = row->GetField(1);
01114
01115 delete row;
01116
01117 ReadIntCfg(sqlio::cfg_Version, fSQLIOversion)
01118 ReadBoolCfg(sqlio::cfg_UseSufixes, fUseSuffixes)
01119 ReadIntCfg(sqlio::cfg_ArrayLimit, fArrayLimit)
01120 ReadStrCfg(sqlio::cfg_TablesType, fTablesType)
01121 ReadIntCfg(sqlio::cfg_UseTransactions, fUseTransactions)
01122 ReadIntCfg(sqlio::cfg_UseIndexes, fUseIndexes)
01123 ReadIntCfg(sqlio::cfg_ModifyCounter, fModifyCounter)
01124 ReadIntCfg(sqlio::cfg_LockingMode, lock)
01125 {
01126 Error("ReadConfigurations","Invalid configuration field %s", field.Data());
01127 fSQLIOversion = 0;
01128 break;
01129 }
01130 }
01131
01132 delete res;
01133
01134 return (fSQLIOversion>0);
01135 }
01136
01137
01138 void TSQLFile::CreateBasicTables()
01139 {
01140
01141
01142
01143
01144 TString sqlcmd;
01145
01146 const char* quote = SQLIdentifierQuote();
01147 const char* vquote = SQLValueQuote();
01148
01149 if (SQLTestTable(sqlio::ConfigTable)) {
01150 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::ConfigTable, quote);
01151 SQLQuery(sqlcmd.Data());
01152 }
01153
01154 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s)",
01155 quote, sqlio::ConfigTable, quote,
01156 quote, sqlio::CT_Field, quote, SQLSmallTextType(),
01157 quote, sqlio::CT_Value, quote, SQLSmallTextType());
01158 if ((fTablesType.Length()>0) && IsMySQL()) {
01159 sqlcmd +=" TYPE=";
01160 sqlcmd += fTablesType;
01161 }
01162
01163 SQLQuery(sqlcmd.Data());
01164
01165 #define WrintCfg(name, type, value) \
01166 { \
01167 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s%s%s, %s"type"%s)", \
01168 quote, sqlio::ConfigTable, quote, \
01169 vquote, name, vquote, \
01170 vquote, value, vquote); \
01171 SQLQuery(sqlcmd.Data()); \
01172 }
01173
01174 WrintCfg(sqlio::cfg_Version, "%d", fSQLIOversion);
01175 WrintCfg(sqlio::cfg_UseSufixes, "%s", fUseSuffixes ? sqlio::True : sqlio::False);
01176 WrintCfg(sqlio::cfg_ArrayLimit, "%d", fArrayLimit);
01177 WrintCfg(sqlio::cfg_TablesType, "%s", fTablesType.Data());
01178 WrintCfg(sqlio::cfg_UseTransactions, "%d", fUseTransactions);
01179 WrintCfg(sqlio::cfg_UseIndexes, "%d", fUseIndexes);
01180 WrintCfg(sqlio::cfg_ModifyCounter, "%d", fModifyCounter);
01181 WrintCfg(sqlio::cfg_LockingMode, "%d", kLockBusy);
01182
01183
01184 fCanChangeConfig = kFALSE;
01185
01186 if (SQLTestTable(sqlio::KeysTable)) {
01187 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::KeysTable, quote);
01188 SQLQuery(sqlcmd.Data());
01189 }
01190
01191 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)",
01192 quote, sqlio::KeysTable, quote,
01193 quote, SQLKeyIdColumn(), quote, SQLIntType(),
01194 quote, SQLDirIdColumn(), quote, SQLIntType(),
01195 quote, SQLObjectIdColumn(), quote, SQLIntType(),
01196 quote, sqlio::KT_Name, quote, SQLSmallTextType(),
01197 quote, sqlio::KT_Title, quote, SQLSmallTextType(),
01198 quote, sqlio::KT_Datetime, quote, SQLDatetimeType(),
01199 quote, sqlio::KT_Cycle, quote, SQLIntType(),
01200 quote, sqlio::KT_Class, quote, SQLSmallTextType());
01201
01202 if ((fTablesType.Length()>0) && IsMySQL()) {
01203 sqlcmd +=" TYPE=";
01204 sqlcmd += fTablesType;
01205 }
01206
01207 SQLQuery(sqlcmd.Data());
01208
01209 if (GetUseIndexes()>kIndexesNone) {
01210 sqlcmd.Form("CREATE UNIQUE INDEX %s%s%s ON %s%s%s (%s%s%s)",
01211 quote, sqlio::KeysTableIndex, quote,
01212 quote, sqlio::KeysTable, quote,
01213 quote, SQLKeyIdColumn(), quote);
01214 SQLQuery(sqlcmd.Data());
01215 }
01216 }
01217
01218
01219 void TSQLFile::IncrementModifyCounter()
01220 {
01221
01222
01223
01224
01225
01226 if (!IsWritable()) {
01227 Error("IncrementModifyCounter","Cannot update tables without write accsess");
01228 return;
01229 }
01230
01231 TString sqlcmd;
01232 const char* quote = SQLIdentifierQuote();
01233 const char* vquote = SQLValueQuote();
01234
01235 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%d WHERE %s%s%s=%s%s%s",
01236 quote, sqlio::ConfigTable, quote,
01237 quote, sqlio::CT_Value, quote, ++fModifyCounter,
01238 quote, sqlio::CT_Field, quote,
01239 vquote, sqlio::cfg_ModifyCounter, vquote);
01240 SQLQuery(sqlcmd.Data());
01241 }
01242
01243
01244 TString TSQLFile::MakeSelectQuery(TClass* cl)
01245 {
01246
01247
01248
01249
01250
01251
01252
01253
01254 TString res = "";
01255 TSQLClassInfo* sqlinfo = FindSQLClassInfo(cl);
01256 if (sqlinfo==0) return res;
01257
01258 TString columns, tables;
01259 Int_t tablecnt = 0;
01260
01261 if (!ProduceClassSelectQuery(cl->GetStreamerInfo(), sqlinfo, columns, tables, tablecnt))
01262 return res;
01263
01264 res.Form("SELECT %s FROM %s", columns.Data(), tables.Data());
01265
01266 return res;
01267 }
01268
01269
01270 Bool_t TSQLFile::ProduceClassSelectQuery(TVirtualStreamerInfo* info,
01271 TSQLClassInfo* sqlinfo,
01272 TString& columns,
01273 TString& tables,
01274 Int_t& tablecnt)
01275 {
01276
01277
01278
01279 if ((info==0) || (sqlinfo==0)) return kFALSE;
01280
01281 if (!sqlinfo->IsClassTableExist()) return kFALSE;
01282
01283 const char* quote = SQLIdentifierQuote();
01284
01285 TString table_syn;
01286 table_syn.Form("t%d", ++tablecnt);
01287
01288 Bool_t start = tables.Length()==0;
01289
01290 TString buf;
01291
01292 if (start)
01293 buf.Form("%s AS %s", sqlinfo->GetClassTableName(), table_syn.Data());
01294 else
01295 buf.Form(" LEFT JOIN %s AS %s USING(%s%s%s)",
01296 sqlinfo->GetClassTableName(), table_syn.Data(),
01297 quote, SQLObjectIdColumn(), quote);
01298
01299 tables += buf;
01300
01301 if (start)
01302 columns.Form("%s.%s%s%s",table_syn.Data(), quote, SQLObjectIdColumn(), quote);
01303
01304 if (info->GetClass()==TObject::Class()) {
01305 buf.Form(", %s.%s",table_syn.Data(), sqlio::TObjectUniqueId);
01306 columns+=buf;
01307 buf.Form(", %s.%s",table_syn.Data(), sqlio::TObjectBits);
01308 columns+=buf;
01309 buf.Form(", %s.%s",table_syn.Data(), sqlio::TObjectProcessId);
01310 columns+=buf;
01311 return kTRUE;
01312 }
01313
01314 TIter iter(info->GetElements());
01315 TStreamerElement* elem = 0;
01316
01317 while ((elem = (TStreamerElement*) iter()) != 0) {
01318 Int_t coltype = TSQLStructure::DefineElementColumnType(elem, this);
01319 TString colname = TSQLStructure::DefineElementColumnName(elem, this);
01320
01321 buf = "";
01322 switch (coltype) {
01323
01324 case TSQLStructure::kColObject:
01325 case TSQLStructure::kColObjectPtr:
01326 case TSQLStructure::kColTString:
01327 case TSQLStructure::kColSimple: {
01328 buf.Form(", %s.%s%s%s",table_syn.Data(), quote, colname.Data(), quote);
01329 columns+=buf;
01330 break;
01331 }
01332
01333 case TSQLStructure::kColParent: {
01334 TClass* parentcl = elem->GetClassPointer();
01335 ProduceClassSelectQuery(parentcl->GetStreamerInfo(),
01336 FindSQLClassInfo(parentcl),
01337 columns, tables, tablecnt);
01338 break;
01339 }
01340
01341 case TSQLStructure::kColSimpleArray: {
01342 for(Int_t n=0;n<elem->GetArrayLength();n++) {
01343 colname = TSQLStructure::DefineElementColumnName(elem, this, n);
01344 buf.Form(", %s.%s%s%s",table_syn.Data(), quote, colname.Data(), quote);
01345 columns+=buf;
01346 }
01347 break;
01348 }
01349 }
01350 }
01351
01352 return (columns.Length()>0) && (tables.Length()>0);
01353 }
01354
01355
01356 Bool_t TSQLFile::IsTablesExists()
01357 {
01358
01359
01360 return SQLTestTable(sqlio::KeysTable) && SQLTestTable(sqlio::ConfigTable);
01361 }
01362
01363
01364 Bool_t TSQLFile::IsWriteAccess()
01365 {
01366
01367
01368 return GetLocking()==kLockFree;
01369 }
01370
01371
01372 void TSQLFile::SetLocking(Int_t mode)
01373 {
01374
01375
01376 TString sqlcmd;
01377 const char* quote = SQLIdentifierQuote();
01378 const char* vquote = SQLValueQuote();
01379
01380 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%d WHERE %s%s%s=%s%s%s",
01381 quote, sqlio::ConfigTable, quote,
01382 quote, sqlio::CT_Value, quote, mode,
01383 quote, sqlio::CT_Field, quote,
01384 vquote, sqlio::cfg_LockingMode, vquote);
01385 SQLQuery(sqlcmd.Data());
01386 }
01387
01388
01389 Int_t TSQLFile::GetLocking()
01390 {
01391
01392
01393 const char* quote = SQLIdentifierQuote();
01394 const char* vquote = SQLValueQuote();
01395
01396 TString sqlcmd;
01397 sqlcmd.Form("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s=%s%s%s",
01398 quote, sqlio::CT_Value, quote,
01399 quote, sqlio::ConfigTable, quote,
01400 quote, sqlio::CT_Field, quote,
01401 vquote, sqlio::cfg_LockingMode, vquote);
01402
01403 TSQLResult* res = SQLQuery(sqlcmd.Data(), 1);
01404 TSQLRow* row = (res==0) ? 0 : res->Next();
01405 TString field = (row==0) ? "" : row->GetField(0);
01406 delete row;
01407 delete res;
01408
01409 if (field.Length()==0) return kLockFree;
01410
01411 return field.Atoi();
01412 }
01413
01414
01415 Bool_t TSQLFile::IsReadAccess()
01416 {
01417
01418
01419 return kTRUE;
01420 }
01421
01422
01423 TSQLResult* TSQLFile::SQLQuery(const char* cmd, Int_t flag, Bool_t* ok)
01424 {
01425
01426
01427
01428
01429
01430
01431
01432
01433 if (fLogFile!=0)
01434 *fLogFile << cmd << endl;
01435
01436 if (ok!=0) *ok = kFALSE;
01437
01438 if (fSQL==0) return 0;
01439
01440 if (gDebug>2) Info("SQLQuery", "%s", cmd);
01441
01442 fQuerisCounter++;
01443
01444 if (flag==0) {
01445 Bool_t res = fSQL->Exec(cmd);
01446 if (ok!=0) *ok = res;
01447 return 0;
01448 }
01449
01450 TSQLResult* res = fSQL->Query(cmd);
01451 if (ok!=0) *ok = res!=0;
01452 if (res==0) return 0;
01453
01454
01455 return res;
01456 }
01457
01458
01459 Bool_t TSQLFile::SQLCanStatement()
01460 {
01461
01462
01463 if (fSQL==0) return kFALSE;
01464
01465 if (!fSQL->HasStatement()) return kFALSE;
01466
01467 return kTRUE;
01468 }
01469
01470
01471 TSQLStatement* TSQLFile::SQLStatement(const char* cmd, Int_t bufsize)
01472 {
01473
01474
01475 if (fSQL==0) return 0;
01476
01477 if (!fSQL->HasStatement()) return 0;
01478
01479 if (gDebug>1)
01480 Info("SQLStatement", "%s", cmd);
01481
01482 fStmtCounter++;
01483 fQuerisCounter++;
01484
01485 return fSQL->Statement(cmd, bufsize);
01486 }
01487
01488
01489 void TSQLFile::SQLDeleteStatement(TSQLStatement* stmt)
01490 {
01491
01492
01493 if (stmt==0) return;
01494
01495 fStmtCounter--;
01496
01497 delete stmt;
01498 }
01499
01500
01501 Bool_t TSQLFile::SQLApplyCommands(TObjArray* cmds)
01502 {
01503
01504
01505
01506 if ((cmds==0) || (fSQL==0)) return kFALSE;
01507
01508 Bool_t ok = kTRUE;
01509 TIter iter(cmds);
01510 TObject* cmd= 0;
01511 while ((cmd=iter())!=0) {
01512 SQLQuery(cmd->GetName(),0,&ok);
01513 if(!ok) break;
01514 }
01515
01516 return ok;
01517 }
01518
01519
01520 Bool_t TSQLFile::SQLTestTable(const char* tablename)
01521 {
01522
01523
01524 if (fSQL==0) return kFALSE;
01525
01526 if (fSQL->HasTable(tablename)) return kTRUE;
01527
01528 TString buf(tablename);
01529 buf.ToLower();
01530 if (fSQL->HasTable(buf.Data())) return kTRUE;
01531 buf.ToUpper();
01532 return fSQL->HasTable(buf.Data());
01533 }
01534
01535
01536 Long64_t TSQLFile::SQLMaximumValue(const char* tablename, const char* columnname)
01537 {
01538
01539
01540
01541 if (fSQL==0) return -1;
01542
01543 if (gDebug>2)
01544 Info("SQLMaximumValue","Requests for %s column %s", tablename, columnname);
01545
01546 const char* quote = SQLIdentifierQuote();
01547
01548 TString query;
01549 query.Form("SELECT MAX(%s%s%s) FROM %s%s%s",
01550 quote, columnname, quote,
01551 quote, tablename, quote);
01552 TSQLResult* res = SQLQuery(query.Data(), 1);
01553
01554 if (res==0) return -1;
01555
01556 TSQLRow* row = res->Next();
01557
01558 Long64_t maxid = -1;
01559 if (row!=0)
01560 if (row->GetField(0)!=0)
01561 maxid = sqlio::atol64(row->GetField(0));
01562
01563 delete row;
01564 delete res;
01565
01566 if (gDebug>2)
01567 Info("SQLMaximumValue","Result = %lld",maxid);;
01568
01569 return maxid;
01570 }
01571
01572
01573 void TSQLFile::SQLDeleteAllTables()
01574 {
01575
01576
01577 if (fSQL==0) return;
01578
01579 TList* tables = fSQL->GetTablesList();
01580 if (tables==0) return;
01581
01582 TString sqlcmd;
01583 const char* quote = SQLIdentifierQuote();
01584
01585 TIter iter(tables);
01586 TObject* obj = 0;
01587 while ((obj=iter())!=0) {
01588 sqlcmd.Form("DROP TABLE %s%s%s", quote, obj->GetName(), quote);
01589 SQLQuery(sqlcmd.Data());
01590 }
01591 delete tables;
01592 }
01593
01594
01595 Bool_t TSQLFile::SQLStartTransaction()
01596 {
01597
01598
01599 return fSQL ? fSQL->StartTransaction() : kFALSE;
01600 }
01601
01602
01603 Bool_t TSQLFile::SQLCommit()
01604 {
01605
01606
01607 return fSQL ? fSQL->Commit() : kFALSE;
01608 }
01609
01610
01611 Bool_t TSQLFile::SQLRollback()
01612 {
01613
01614
01615 return fSQL ? fSQL->Rollback() : kFALSE;
01616 }
01617
01618
01619 Int_t TSQLFile::SQLMaxIdentifierLength()
01620 {
01621
01622
01623 Int_t maxlen = fSQL==0 ? 32 : fSQL->GetMaxIdentifierLength();
01624
01625
01626 if (maxlen<10) maxlen = 10;
01627
01628 return maxlen;
01629 }
01630
01631
01632 void TSQLFile::DeleteKeyFromDB(Long64_t keyid)
01633 {
01634
01635
01636
01637 if (!IsWritable() || (keyid<0) || (fSQL==0)) return;
01638
01639 TString sqlcmd;
01640 const char* quote = SQLIdentifierQuote();
01641
01642 sqlcmd.Form("SELECT MIN(%s%s%s), MAX(%s%s%s) FROM %s%s%s WHERE %s%s%s=%lld",
01643 quote, SQLObjectIdColumn(), quote,
01644 quote, SQLObjectIdColumn(), quote,
01645 quote, sqlio::ObjectsTable, quote,
01646 quote, SQLKeyIdColumn(), quote, keyid);
01647 TSQLResult* res = SQLQuery(sqlcmd.Data(), 2);
01648 TSQLRow* row = res==0 ? 0 : res->Next();
01649 Long64_t minid(1), maxid(0);
01650
01651 if ((row!=0) && (row->GetField(0)!=0) && (row->GetField(1)!=0)) {
01652 minid = sqlio::atol64(row->GetField(0));
01653 maxid = sqlio::atol64(row->GetField(1));
01654 }
01655
01656 delete row;
01657 delete res;
01658
01659
01660 if (minid<=maxid) {
01661 TIter iter(fSQLClassInfos);
01662 TSQLClassInfo* info = 0;
01663 TString querymask, query;
01664 querymask.Form("DELETE FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld",
01665 quote, "%s", quote,
01666 quote, SQLObjectIdColumn(), quote,
01667 minid, maxid);
01668
01669 while ((info = (TSQLClassInfo*) iter()) !=0 ) {
01670
01671 if (info->IsClassTableExist()) {
01672 query.Form(querymask.Data(), info->GetClassTableName());
01673 SQLQuery(query.Data());
01674 }
01675
01676 if (info->IsRawTableExist()) {
01677 query.Form(querymask.Data(), info->GetRawTableName());
01678 SQLQuery(query.Data());
01679 }
01680 }
01681 }
01682
01683 sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, keyid);
01684 SQLQuery(sqlcmd.Data());
01685
01686 sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote, keyid);
01687 SQLQuery(sqlcmd.Data());
01688
01689 IncrementModifyCounter();
01690 }
01691
01692
01693 TKeySQL* TSQLFile::FindSQLKey(TDirectory* dir, Long64_t keyid)
01694 {
01695
01696
01697 if (dir==0) return 0;
01698
01699 TIter next(dir->GetListOfKeys());
01700 TObject* obj = 0;
01701
01702 while ((obj = next())!=0) {
01703 TKeySQL* key = dynamic_cast<TKeySQL*> (obj);
01704 if (key!=0)
01705 if (key->GetDBKeyId()==keyid) return key;
01706 }
01707
01708 return 0;
01709 }
01710
01711
01712 Bool_t TSQLFile::WriteKeyData(TKeySQL* key)
01713 {
01714
01715
01716 if ((fSQL==0) || (key==0)) return kFALSE;
01717
01718 if (!IsTablesExists()) CreateBasicTables();
01719
01720 TString sqlcmd;
01721 const char* valuequote = SQLValueQuote();
01722 const char* quote = SQLIdentifierQuote();
01723
01724 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %lld, %lld, %s%s%s, %s%s%s, %s%s%s, %d, %s%s%s)",
01725 quote, sqlio::KeysTable, quote,
01726 key->GetDBKeyId(), key->GetDBDirId(), key->GetDBObjId(),
01727 valuequote, key->GetName(), valuequote,
01728 valuequote, key->GetTitle(), valuequote,
01729 valuequote, key->GetDatime().AsSQLString(), valuequote,
01730 key->GetCycle(),
01731 valuequote, key->GetClassName(), valuequote);
01732
01733 Bool_t ok = kTRUE;
01734
01735 SQLQuery(sqlcmd.Data(), 0, &ok);
01736
01737 if (ok) IncrementModifyCounter();
01738
01739 return ok;
01740 }
01741
01742
01743 Bool_t TSQLFile::UpdateKeyData(TKeySQL* key)
01744 {
01745
01746
01747 if ((fSQL==0) || (key==0)) return kFALSE;
01748
01749 TString sqlcmd;
01750 const char* valuequote = SQLValueQuote();
01751 const char* quote = SQLIdentifierQuote();
01752
01753 TString keyname = key->GetName();
01754 TString keytitle = key->GetTitle();
01755 TString keydatime = key->GetDatime().AsSQLString();
01756
01757 TSQLStructure::AddStrBrackets(keyname, valuequote);
01758 TSQLStructure::AddStrBrackets(keytitle, valuequote);
01759 TSQLStructure::AddStrBrackets(keydatime, valuequote);
01760
01761 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s, %s%s%s=%d WHERE %s%s%s=%lld",
01762 quote, sqlio::KeysTable, quote,
01763 quote, sqlio::KT_Name, quote, keyname.Data(),
01764 quote, sqlio::KT_Title, quote, keytitle.Data(),
01765 quote, sqlio::KT_Datetime, quote, keydatime.Data(),
01766 quote, sqlio::KT_Cycle, quote, key->GetCycle(),
01767 quote, SQLKeyIdColumn(), quote, key->GetDBKeyId());
01768
01769 Bool_t ok = kTRUE;
01770
01771 SQLQuery(sqlcmd.Data(), 0, &ok);
01772
01773 if (ok) IncrementModifyCounter();
01774
01775 return ok;
01776 }
01777
01778
01779 Long64_t TSQLFile::DefineNextKeyId()
01780 {
01781
01782
01783 Long64_t max = -1;
01784
01785 if (SQLTestTable(sqlio::KeysTable))
01786 max = SQLMaximumValue(sqlio::KeysTable, SQLKeyIdColumn());
01787
01788 if (max<0) return sqlio::Ids_FirstKey;
01789
01790 return max+1;
01791 }
01792
01793
01794 TSQLClassInfo* TSQLFile::FindSQLClassInfo(const char* clname, Int_t version)
01795 {
01796
01797
01798 if (fSQLClassInfos==0) return 0;
01799
01800 TIter iter(fSQLClassInfos);
01801 TSQLClassInfo* info = 0;
01802
01803 while ((info = (TSQLClassInfo*) iter()) !=0 ) {
01804 if (strcmp(info->GetName(), clname)==0)
01805 if (info->GetClassVersion()==version) return info;
01806 }
01807 return 0;
01808 }
01809
01810
01811 TSQLClassInfo* TSQLFile::FindSQLClassInfo(const TClass* cl)
01812 {
01813
01814
01815 return FindSQLClassInfo(cl->GetName(), cl->GetClassVersion());
01816 }
01817
01818
01819 TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const char* clname, Int_t version)
01820 {
01821
01822
01823 TSQLClassInfo* info = FindSQLClassInfo(clname, version);
01824 if (info!=0) return info;
01825
01826 if (fSQL==0) return 0;
01827
01828 Long64_t maxid = 0;
01829
01830 if (fSQLClassInfos!=0) {
01831 TIter iter(fSQLClassInfos);
01832 info = 0;
01833 while ((info = (TSQLClassInfo*) iter()) !=0 ) {
01834 if (info->GetClassId()>maxid)
01835 maxid = info->GetClassId();
01836 }
01837 }
01838
01839 info = new TSQLClassInfo(maxid+1, clname, version);
01840
01841 info->SetClassTableName(DefineTableName(clname, version, kFALSE));
01842 info->SetRawTableName(DefineTableName(clname, version, kTRUE));
01843
01844 if (fSQLClassInfos==0) fSQLClassInfos = new TList;
01845 fSQLClassInfos->Add(info);
01846
01847 return info;
01848 }
01849
01850
01851 TString TSQLFile::DefineTableName(const char* clname, Int_t version, Bool_t rawtable)
01852 {
01853
01854
01855 Int_t maxlen = SQLMaxIdentifierLength();
01856
01857 TString res;
01858
01859 const char *suffix = rawtable ? "_raw" : "_ver";
01860
01861 res.Form("%s%s%d", clname, suffix, version);
01862
01863 if ((res.Length() <= maxlen) && !HasTable(res.Data()))
01864 return res;
01865
01866 TString scnt;
01867
01868 Int_t len = strlen(clname);
01869 Int_t cnt = version;
01870 if (cnt>100) cnt = 0;
01871
01872 do {
01873 scnt.Form("%d%s",cnt, suffix);
01874 Int_t numlen = scnt.Length();
01875 if (numlen>=maxlen-2) break;
01876
01877 res = clname;
01878
01879 if (len + numlen > maxlen)
01880 res.Resize(maxlen - numlen);
01881
01882 res+=scnt;
01883
01884 if (!HasTable(res.Data())) return res;
01885
01886 cnt++;
01887
01888 } while (cnt<10000);
01889
01890 Error("DefineTableName","Cannot produce table name for class %s ver %d", clname, version);
01891 res.Form("%s%s%d", clname, suffix, version);
01892
01893 return res;
01894 }
01895
01896
01897 Bool_t TSQLFile::HasTable(const char* name)
01898 {
01899
01900
01901 if (fSQLClassInfos==0) return kFALSE;
01902
01903 TIter iter(fSQLClassInfos);
01904 TSQLClassInfo* info = 0;
01905 while ((info = (TSQLClassInfo*) iter()) !=0 ) {
01906 if (strcmp(info->GetClassTableName(), name)==0) return kTRUE;
01907 if (strcmp(info->GetRawTableName(), name)==0) return kTRUE;
01908 }
01909
01910 return kFALSE;
01911 }
01912
01913
01914 TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const TClass* cl)
01915 {
01916
01917
01918 return RequestSQLClassInfo(cl->GetName(), cl->GetClassVersion());
01919 }
01920
01921
01922 void TSQLFile::ReadSQLClassInfos()
01923 {
01924
01925
01926 if (fSQL==0) return;
01927
01928 fIdsTableExists = SQLTestTable(sqlio::IdsTable);
01929
01930 if (!fIdsTableExists) return;
01931
01932 TString sqlcmd;
01933 const char* quote = SQLIdentifierQuote();
01934
01935 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s",
01936 quote, sqlio::IdsTable, quote,
01937 quote, sqlio::IT_Type, quote, TSQLStructure::kIdTable,
01938 quote, sqlio::IT_TableID, quote);
01939
01940 TSQLResult* res = SQLQuery(sqlcmd.Data(), 1);
01941
01942 TSQLRow* row = 0;
01943
01944 if (res!=0)
01945 while ((row = res->Next())!=0) {
01946 Long64_t tableid = sqlio::atol64(row->GetField(0));
01947 Int_t version = atoi(row->GetField(1));
01948
01949 const char* classname = row->GetField(3);
01950 const char* classtable = row->GetField(4);
01951
01952 TSQLClassInfo* info = new TSQLClassInfo(tableid, classname, version);
01953 info->SetClassTableName(classtable);
01954
01955 if (fSQLClassInfos==0) fSQLClassInfos = new TList;
01956 fSQLClassInfos->Add(info);
01957
01958 delete row;
01959 }
01960 delete res;
01961
01962
01963 TIter next(fSQLClassInfos);
01964 TSQLClassInfo* info = 0;
01965
01966 while ((info = (TSQLClassInfo*) next()) != 0) {
01967 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %lld ORDER BY %s%s%s",
01968 quote, sqlio::IdsTable, quote,
01969 quote, sqlio::IT_TableID, quote, info->GetClassId(),
01970 quote, sqlio::IT_SubID, quote);
01971 res = SQLQuery(sqlcmd.Data(), 1);
01972
01973 TObjArray* cols = 0;
01974
01975 if (res!=0)
01976 while ((row = res->Next())!=0) {
01977
01978 Int_t typ = atoi(row->GetField(2));
01979
01980 const char* fullname = row->GetField(3);
01981 const char* sqlname = row->GetField(4);
01982 const char* info2 = row->GetField(5);
01983
01984 if (typ==TSQLStructure::kIdColumn) {
01985 if (cols==0) cols = new TObjArray;
01986 cols->Add(new TSQLClassColumnInfo(fullname, sqlname, info2));
01987 }
01988
01989 delete row;
01990 }
01991
01992 delete res;
01993
01994 info->SetColumns(cols);
01995 }
01996
01997 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s",
01998 quote, sqlio::IdsTable, quote,
01999 quote, sqlio::IT_Type, quote, TSQLStructure::kIdRawTable,
02000 quote, sqlio::IT_TableID, quote);
02001
02002 res = SQLQuery(sqlcmd.Data(), 1);
02003
02004 if (res!=0)
02005 while ((row = res->Next())!=0) {
02006 Long64_t tableid = sqlio::atol64(row->GetField(0));
02007 Int_t version = atoi(row->GetField(1));
02008
02009 const char* classname = row->GetField(3);
02010 const char* rawtable = row->GetField(4);
02011
02012 TSQLClassInfo* info2 = FindSQLClassInfo(classname, version);
02013
02014 if (info2==0) {
02015 info2 = new TSQLClassInfo(tableid, classname, version);
02016
02017 if (fSQLClassInfos==0) fSQLClassInfos = new TList;
02018 fSQLClassInfos->Add(info2);
02019 }
02020
02021 info2->SetRawTableName(rawtable);
02022 info2->SetRawExist(kTRUE);
02023
02024 delete row;
02025 }
02026
02027 delete res;
02028 }
02029
02030
02031
02032 void TSQLFile::AddIdEntry(Long64_t tableid, Int_t subid, Int_t type,
02033 const char* name, const char* sqlname, const char* info)
02034 {
02035
02036
02037 if ((fSQL==0) || !IsWritable()) return;
02038
02039 TString sqlcmd;
02040 const char* valuequote = SQLValueQuote();
02041 const char* quote = SQLIdentifierQuote();
02042
02043 if (!fIdsTableExists) {
02044
02045 if (SQLTestTable(sqlio::IdsTable)) {
02046 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::IdsTable, quote);
02047 SQLQuery(sqlcmd.Data());
02048 }
02049
02050 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)",
02051 quote, sqlio::IdsTable, quote,
02052 quote, sqlio::IT_TableID, quote, SQLIntType(),
02053 quote, sqlio::IT_SubID, quote, SQLIntType(),
02054 quote, sqlio::IT_Type, quote, SQLIntType(),
02055 quote, sqlio::IT_FullName, quote, SQLSmallTextType(),
02056 quote, sqlio::IT_SQLName, quote, SQLSmallTextType(),
02057 quote, sqlio::IT_Info, quote, SQLSmallTextType());
02058 if ((fTablesType.Length()>0) && IsMySQL()) {
02059 sqlcmd +=" TYPE=";
02060 sqlcmd += fTablesType;
02061 }
02062 SQLQuery(sqlcmd.Data());
02063
02064 fIdsTableExists = kTRUE;
02065 }
02066
02067 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %d, %d, %s%s%s, %s%s%s, %s%s%s)",
02068 quote, sqlio::IdsTable, quote,
02069 tableid, subid, type,
02070 valuequote, name, valuequote,
02071 valuequote, sqlname, valuequote,
02072 valuequote, info, valuequote);
02073
02074 SQLQuery(sqlcmd.Data());
02075 }
02076
02077
02078 Bool_t TSQLFile::CreateClassTable(TSQLClassInfo* sqlinfo, TObjArray* colinfos)
02079 {
02080
02081
02082 if (sqlinfo==0) return kFALSE;
02083
02084
02085 if (colinfos==0) return sqlinfo->IsClassTableExist();
02086
02087 if (sqlinfo->IsClassTableExist()) {
02088 if (colinfos!=0) {
02089 colinfos->Delete();
02090 delete colinfos;
02091
02092 }
02093 return kTRUE;
02094 }
02095
02096 if (gDebug>2)
02097 Info("CreateClassTable", "cl:%s", sqlinfo->GetName());
02098
02099 const char* quote = SQLIdentifierQuote();
02100
02101 AddIdEntry(sqlinfo->GetClassId(),
02102 sqlinfo->GetClassVersion(),
02103 TSQLStructure::kIdTable,
02104 sqlinfo->GetName(),
02105 sqlinfo->GetClassTableName(),
02106 "Main class table");
02107
02108 TString sqlcmd;
02109 sqlcmd.Form("CREATE TABLE %s%s%s (",
02110 quote, sqlinfo->GetClassTableName(), quote);
02111
02112 TIter iter(colinfos);
02113 TSQLClassColumnInfo* col;
02114 Bool_t first = kTRUE;
02115 Bool_t forcequote = IsOracle();
02116 Int_t colid = 0;
02117 while ((col=(TSQLClassColumnInfo*)iter())!=0) {
02118 if (!first) sqlcmd+=", "; else first = false;
02119
02120 const char* colname = col->GetSQLName();
02121 if ((strpbrk(colname,"[:.]<>")!=0) || forcequote) {
02122 sqlcmd += quote;
02123 sqlcmd += colname;
02124 sqlcmd += quote;
02125 sqlcmd += " ";
02126 } else {
02127 sqlcmd += colname,
02128 sqlcmd += " ";
02129 }
02130
02131 sqlcmd += col->GetSQLType();
02132
02133 AddIdEntry(sqlinfo->GetClassId(),
02134 colid++,
02135 TSQLStructure::kIdColumn,
02136 col->GetName(),
02137 col->GetSQLName(),
02138 col->GetSQLType());
02139 }
02140 sqlcmd += ")";
02141
02142 if ((fTablesType.Length()>0) && IsMySQL()) {
02143 sqlcmd +=" TYPE=";
02144 sqlcmd += fTablesType;
02145 }
02146
02147 SQLQuery(sqlcmd.Data());
02148
02149 sqlinfo->SetColumns(colinfos);
02150
02151 if (GetUseIndexes()>kIndexesBasic) {
02152
02153 TString indxname = sqlinfo->GetClassTableName();
02154 indxname.ReplaceAll("_ver","_i1x");
02155
02156 sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I1%s ON %s%s%s (%s%s%s)",
02157 quote, indxname.Data(), quote,
02158 quote, sqlinfo->GetClassTableName(), quote,
02159 quote, SQLObjectIdColumn(), quote);
02160 SQLQuery(sqlcmd.Data());
02161 }
02162
02163 return kTRUE;
02164 }
02165
02166
02167 Bool_t TSQLFile::CreateRawTable(TSQLClassInfo* sqlinfo)
02168 {
02169
02170 if (sqlinfo==0) return kFALSE;
02171
02172 if (sqlinfo->IsRawTableExist()) return kTRUE;
02173
02174 const char* quote = SQLIdentifierQuote();
02175
02176 if (gDebug>2)
02177 Info("CreateRawTable", "%s", sqlinfo->GetName());
02178
02179 TString sqlcmd;
02180
02181 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)",
02182 quote, sqlinfo->GetRawTableName(), quote,
02183 quote, SQLObjectIdColumn(), quote, SQLIntType(),
02184 quote, SQLRawIdColumn(), quote, SQLIntType(),
02185 sqlio::BT_Field, SQLSmallTextType(),
02186 sqlio::BT_Value, SQLSmallTextType());
02187
02188 if ((fTablesType.Length()>0) && IsMySQL()) {
02189 sqlcmd +=" TYPE=";
02190 sqlcmd += fTablesType;
02191 }
02192
02193 SQLQuery(sqlcmd.Data());
02194 sqlinfo->SetRawExist(kTRUE);
02195
02196 if (GetUseIndexes()>kIndexesClass) {
02197 TString indxname = sqlinfo->GetClassTableName();
02198 indxname.ReplaceAll("_ver","_i2x");
02199
02200 sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I2%s ON %s%s%s (%s%s%s, %s%s%s)",
02201 quote, indxname.Data(), quote,
02202 quote, sqlinfo->GetRawTableName(), quote,
02203 quote, SQLObjectIdColumn(), quote,
02204 quote, SQLRawIdColumn(), quote);
02205 SQLQuery(sqlcmd.Data());
02206 }
02207
02208 AddIdEntry(sqlinfo->GetClassId(),
02209 sqlinfo->GetClassVersion(),
02210 TSQLStructure::kIdRawTable,
02211 sqlinfo->GetName(),
02212 sqlinfo->GetRawTableName(),
02213 "Raw data class table");
02214
02215 return kTRUE;
02216 }
02217
02218
02219 Bool_t TSQLFile::VerifyLongStringTable()
02220 {
02221
02222
02223
02224 if (fSQL==0) return kFALSE;
02225
02226 if (SQLTestTable(sqlio::StringsTable)) return kTRUE;
02227
02228 const char* quote = SQLIdentifierQuote();
02229
02230 TString sqlcmd;
02231 sqlcmd.Form("CREATE TABLE %s (%s%s%s %s, %s%s%s %s, %s %s)",
02232 sqlio::StringsTable,
02233 quote, SQLObjectIdColumn(), quote, SQLIntType(),
02234 quote, SQLStrIdColumn(), quote, SQLIntType(),
02235 sqlio::ST_Value, SQLBigTextType());
02236
02237 if (fTablesType.Length()>0) {
02238 sqlcmd +=" TYPE=";
02239 sqlcmd += fTablesType;
02240 }
02241
02242 SQLQuery(sqlcmd.Data());
02243
02244 return kTRUE;
02245 }
02246
02247
02248 TString TSQLFile::CodeLongString(Long64_t objid, Int_t strid)
02249 {
02250
02251 TString res;
02252 res.Form("%s %lld %s %d %s", sqlio::LongStrPrefix, objid, sqlio::LongStrPrefix, strid, sqlio::LongStrPrefix);
02253 return res;
02254 }
02255
02256
02257 Int_t TSQLFile::IsLongStringCode(Long64_t objid, const char* value)
02258 {
02259
02260
02261 if (value==0) return 0;
02262 if (strlen(value)<strlen(sqlio::LongStrPrefix)*3+6) return 0;
02263 if (strstr(value, sqlio::LongStrPrefix)!=value) return 0;
02264
02265 value+=strlen(sqlio::LongStrPrefix);
02266 if (*value++!=' ') return 0;
02267 TString s_strid, s_objid;
02268 if ((*value<'1') || (*value>'9')) return 0;
02269 do {
02270 s_objid.Append(*value++);
02271 } while ((*value!=0) && (*value>='0') && (*value<='9'));
02272
02273 if (*value++ != ' ') return 0;
02274 if ((*value==0) || (strstr(value, sqlio::LongStrPrefix)!=value)) return 0;
02275 value+=strlen(sqlio::LongStrPrefix);
02276 if (*value++!=' ') return 0;
02277
02278 if ((*value<'1') || (*value>'9')) return 0;
02279 do {
02280 s_strid.Append(*value++);
02281 } while ((*value!=0) && (*value>='0') && (*value<='9'));
02282 if (*value++!=' ') return 0;
02283
02284 if ((*value==0) || (strcmp(value, sqlio::LongStrPrefix)!=0)) return 0;
02285
02286 Long64_t objid2 = sqlio::atol64(s_objid.Data());
02287 if (objid2!=objid) return 0;
02288
02289 return atoi(s_strid.Data());
02290 }
02291
02292
02293 Bool_t TSQLFile::GetLongString(Long64_t objid, Int_t strid, TString& value)
02294 {
02295
02296
02297
02298 if (!SQLTestTable(sqlio::StringsTable)) return kFALSE;
02299
02300 TString cmd;
02301 const char* quote = SQLIdentifierQuote();
02302 cmd.Form("SELECT %s FROM %s%s%s WHERE %s%s%s=%lld AND %s%s%s=%d",
02303 sqlio::ST_Value,
02304 quote, sqlio::StringsTable, quote,
02305 quote, SQLObjectIdColumn(), quote, objid,
02306 quote, SQLStrIdColumn(), quote, strid);
02307
02308 TSQLResult* res = SQLQuery(cmd.Data(), 1);
02309 if (res==0) return kFALSE;
02310 TSQLRow* row = res->Next();
02311 if (row==0) { delete res; return kFALSE; }
02312 value = row->GetField(0);
02313
02314 delete row;
02315 delete res;
02316
02317 return kTRUE;
02318 }
02319
02320
02321 Long64_t TSQLFile::VerifyObjectTable()
02322 {
02323
02324
02325
02326
02327 if (fSQL==0) return -1;
02328
02329 Long64_t maxid = -1;
02330
02331 if (gDebug>2)
02332 Info("VerifyObjectTable", "Checks if object table is there");
02333
02334 if (SQLTestTable(sqlio::ObjectsTable))
02335 maxid = SQLMaximumValue(sqlio::ObjectsTable, SQLObjectIdColumn());
02336 else {
02337 TString sqlcmd;
02338 const char* quote = SQLIdentifierQuote();
02339 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)",
02340 quote, sqlio::ObjectsTable, quote,
02341 quote, SQLKeyIdColumn(), quote, SQLIntType(),
02342 quote, SQLObjectIdColumn(), quote, SQLIntType(),
02343 quote, sqlio::OT_Class, quote, SQLSmallTextType(),
02344 quote, sqlio::OT_Version, quote, SQLIntType());
02345
02346 if ((fTablesType.Length()>0) && IsMySQL()) {
02347 sqlcmd +=" TYPE=";
02348 sqlcmd += fTablesType;
02349 }
02350
02351 SQLQuery(sqlcmd.Data());
02352
02353 if (GetUseIndexes()>kIndexesNone) {
02354 sqlcmd.Form("CREATE UNIQUE INDEX %s%s%s ON %s%s%s (%s%s%s)",
02355 quote, sqlio::ObjectsTableIndex, quote,
02356 quote, sqlio::ObjectsTable, quote,
02357 quote, SQLObjectIdColumn(), quote);
02358 SQLQuery(sqlcmd.Data());
02359 }
02360 }
02361
02362 return maxid;
02363 }
02364
02365
02366 Bool_t TSQLFile::SQLObjectInfo(Long64_t objid, TString& clname, Version_t &version)
02367 {
02368
02369
02370 if (fSQL==0) return kFALSE;
02371
02372 TString sqlcmd;
02373 const char* quote = SQLIdentifierQuote();
02374 sqlcmd.Form("SELECT %s%s%s, %s%s%s FROM %s%s%s WHERE %s%s%s=%lld",
02375 quote, sqlio::OT_Class, quote,
02376 quote, sqlio::OT_Version, quote,
02377 quote, sqlio::ObjectsTable, quote,
02378 quote, SQLObjectIdColumn(), quote, objid);
02379 TSQLResult* res = SQLQuery(sqlcmd.Data(), 1);
02380 if (res==0) return kFALSE;
02381 TSQLRow* row = res->Next();
02382 if (row!=0) {
02383 clname = row->GetField(0);
02384 version = atoi(row->GetField(1));
02385 }
02386
02387 delete row;
02388 delete res;
02389 return row!=0;
02390 }
02391
02392
02393 TObjArray* TSQLFile::SQLObjectsInfo(Long64_t keyid)
02394 {
02395
02396
02397 if (fSQL==0) return 0;
02398
02399 TString sqlcmd;
02400 const char* quote = SQLIdentifierQuote();
02401 sqlcmd.Form("SELECT %s%s%s, %s%s%s, %s%s%s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s",
02402 quote, SQLObjectIdColumn(), quote,
02403 quote, sqlio::OT_Class, quote,
02404 quote, sqlio::OT_Version, quote,
02405 quote, sqlio::ObjectsTable, quote,
02406 quote, SQLKeyIdColumn(), quote, keyid,
02407 quote, SQLObjectIdColumn(), quote);
02408
02409 TObjArray* arr = 0;
02410
02411 if (fLogFile!=0)
02412 *fLogFile << sqlcmd << endl;
02413 if (gDebug>2) Info("SQLObjectsInfo", "%s", sqlcmd.Data());
02414 fQuerisCounter++;
02415
02416 TSQLStatement* stmt = SQLStatement(sqlcmd.Data(), 1000);
02417
02418 if (stmt!=0) {
02419 stmt->Process();
02420 stmt->StoreResult();
02421
02422 while (stmt->NextResultRow()) {
02423 Long64_t objid = stmt->GetLong64(0);
02424 const char* clname = stmt->GetString(1);
02425 Int_t version = stmt->GetInt(2);
02426
02427 TSQLObjectInfo* info = new TSQLObjectInfo(objid, clname, version);
02428 if (arr==0) arr = new TObjArray();
02429 arr->Add(info);
02430 }
02431
02432 delete stmt;
02433 return arr;
02434 }
02435
02436 TSQLResult* res = SQLQuery(sqlcmd.Data(), 1);
02437 if (res==0) return 0;
02438
02439 TSQLRow* row = 0;
02440 while ((row = res->Next()) != 0) {
02441 Long64_t objid = atoi(row->GetField(0));
02442 const char* clname = row->GetField(1);
02443 Int_t version = atoi(row->GetField(2));
02444
02445 TSQLObjectInfo* info = new TSQLObjectInfo(objid, clname, version);
02446 if (arr==0) arr = new TObjArray();
02447 arr->Add(info);
02448
02449 delete row;
02450 }
02451 delete res;
02452 return arr;
02453 }
02454
02455
02456 TSQLResult* TSQLFile::GetNormalClassData(Long64_t objid, TSQLClassInfo* sqlinfo)
02457 {
02458
02459
02460 if (!sqlinfo->IsClassTableExist()) return 0;
02461 TString sqlcmd;
02462 const char* quote = SQLIdentifierQuote();
02463 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld",
02464 quote, sqlinfo->GetClassTableName(), quote,
02465 quote, SQLObjectIdColumn(), quote, objid);
02466 return SQLQuery(sqlcmd.Data(), 2);
02467 }
02468
02469
02470 TSQLResult* TSQLFile::GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo* sqlinfo)
02471 {
02472
02473
02474 if (!sqlinfo->IsClassTableExist()) return 0;
02475 TString sqlcmd;
02476 const char* quote = SQLIdentifierQuote();
02477 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld ORDER BY %s%s%s",
02478 quote, sqlinfo->GetClassTableName(), quote,
02479 quote, SQLObjectIdColumn(), quote, minobjid, maxobjid,
02480 quote, SQLObjectIdColumn(), quote);
02481 return SQLQuery(sqlcmd.Data(), 2);
02482 }
02483
02484
02485 TSQLResult* TSQLFile::GetBlobClassData(Long64_t objid, TSQLClassInfo* sqlinfo)
02486 {
02487
02488
02489 if (!sqlinfo->IsRawTableExist()) return 0;
02490 TString sqlcmd;
02491 const char* quote = SQLIdentifierQuote();
02492 sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s",
02493 sqlio::BT_Field, sqlio::BT_Value,
02494 quote, sqlinfo->GetRawTableName(), quote,
02495 quote, SQLObjectIdColumn(), quote, objid,
02496 quote, SQLRawIdColumn(), quote);
02497 return SQLQuery(sqlcmd.Data(), 2);
02498 }
02499
02500
02501 TSQLStatement* TSQLFile::GetBlobClassDataStmt(Long64_t objid, TSQLClassInfo* sqlinfo)
02502 {
02503
02504
02505
02506 if (!sqlinfo->IsRawTableExist()) return 0;
02507
02508 TString sqlcmd;
02509 const char* quote = SQLIdentifierQuote();
02510 sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s",
02511 sqlio::BT_Field, sqlio::BT_Value,
02512 quote, sqlinfo->GetRawTableName(), quote,
02513 quote, SQLObjectIdColumn(), quote, objid,
02514 quote, SQLRawIdColumn(), quote);
02515
02516 if (fLogFile!=0)
02517 *fLogFile << sqlcmd << endl;
02518 if (gDebug>2) Info("BuildStatement", "%s", sqlcmd.Data());
02519 fQuerisCounter++;
02520
02521 TSQLStatement* stmt = SQLStatement(sqlcmd.Data(), 1000);
02522 if (stmt==0) return 0;
02523
02524 stmt->Process();
02525
02526 stmt->StoreResult();
02527
02528 return stmt;
02529 }
02530
02531
02532 Long64_t TSQLFile::StoreObjectInTables(Long64_t keyid, const void* obj, const TClass* cl)
02533 {
02534
02535
02536 if (fSQL==0) return -1;
02537
02538 Long64_t objid = VerifyObjectTable();
02539 if (objid<=0) objid = 1; else objid++;
02540
02541 TBufferSQL2 buffer(TBuffer::kWrite, this);
02542
02543 TSQLStructure* s = buffer.SqlWriteAny(obj, cl, objid);
02544
02545 if ((buffer.GetErrorFlag()>0) && s) {
02546 Error("StoreObjectInTables","Cannot convert object data to TSQLStructure");
02547 objid = -1;
02548 } else {
02549 TObjArray cmds;
02550
02551
02552 if (s && !s->ConvertToTables(this, keyid, &cmds)) {
02553 Error("StoreObjectInTables","Cannot convert to SQL statements");
02554 objid = -1;
02555 } else {
02556 Bool_t needcommit = kFALSE;
02557
02558 if (GetUseTransactions()==kTransactionsAuto) {
02559 SQLStartTransaction();
02560 needcommit = kTRUE;
02561 }
02562
02563 if (!SQLApplyCommands(&cmds)) {
02564 Error("StoreObject","Cannot correctly store object data in database");
02565 objid = -1;
02566 if (needcommit) SQLRollback();
02567 } else {
02568 if (needcommit) SQLCommit();
02569 }
02570 }
02571 cmds.Delete();
02572 }
02573
02574 return objid;
02575 }
02576
02577
02578 const char* TSQLFile::SQLCompatibleType(Int_t typ) const
02579 {
02580
02581
02582
02583 return (typ<0) || (typ>18) ? 0 : fBasicTypes[typ];
02584 }
02585
02586
02587 const char* TSQLFile::SQLIntType() const
02588 {
02589
02590
02591 return SQLCompatibleType(TVirtualStreamerInfo::kInt);
02592 }
02593
02594
02595 Long64_t TSQLFile::DirCreateEntry(TDirectory* dir)
02596 {
02597
02598
02599 TDirectory* mother = dir->GetMotherDir();
02600 if (mother==0) mother = this;
02601
02602
02603 TKeySQL* key = new TKeySQL(mother, dir, dir->GetName(), dir->GetTitle());
02604
02605 return key->GetDBKeyId();
02606 }
02607
02608
02609 Int_t TSQLFile::DirReadKeys(TDirectory* dir)
02610 {
02611
02612
02613
02614 dir->GetListOfKeys()->Delete();
02615
02616 if (gDebug>2)
02617 Info("DirReadKeys","dir = %s id = %lld", dir->GetName(), dir->GetSeekDir());
02618
02619 return StreamKeysForDirectory(dir, kFALSE);
02620 }
02621
02622
02623 void TSQLFile::DirWriteKeys(TDirectory* dir)
02624 {
02625
02626
02627 StreamKeysForDirectory(dir, kTRUE);
02628 }
02629
02630
02631 void TSQLFile::DirWriteHeader(TDirectory* dir)
02632 {
02633
02634
02635 TSQLClassInfo* sqlinfo = FindSQLClassInfo("TDirectory",TDirectoryFile::Class()->GetClassVersion());
02636 if (sqlinfo==0) return;
02637
02638
02639 TKeySQL* key = FindSQLKey(dir->GetMotherDir(), dir->GetSeekDir());
02640 if (key==0) return;
02641
02642 const char* valuequote = SQLValueQuote();
02643 const char* quote = SQLIdentifierQuote();
02644
02645 TString timeC = fDatimeC.AsSQLString();
02646 TSQLStructure::AddStrBrackets(timeC, valuequote);
02647
02648 TString timeM = fDatimeM.AsSQLString();
02649 TSQLStructure::AddStrBrackets(timeM, valuequote);
02650
02651 TString uuid = dir->GetUUID().AsString();
02652 TSQLStructure::AddStrBrackets(uuid, valuequote);
02653
02654 TString sqlcmd;
02655
02656 TString col1name = "CreateTime";
02657 TString col2name = "ModifyTime";
02658 TString col3name = "UUID";
02659 if (GetUseSuffixes()) {
02660 col1name+=sqlio::StrSuffix;
02661 col2name+=sqlio::StrSuffix;
02662 col3name+=sqlio::StrSuffix;
02663 }
02664
02665 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s WHERE %s%s%s=%lld",
02666 quote, sqlinfo->GetClassTableName(), quote,
02667 quote, col1name.Data(), quote, timeC.Data(),
02668 quote, col2name.Data(), quote, timeM.Data(),
02669 quote, col3name.Data(), quote, uuid.Data(),
02670 quote, SQLObjectIdColumn(), quote, key->GetDBObjId());
02671
02672 SQLQuery(sqlcmd.Data());
02673 }
02674
02675
02676 void TSQLFile::Streamer(TBuffer &b)
02677 {
02678
02679
02680
02681
02682 TString sbuf;
02683
02684 if (b.IsReading()) {
02685 Version_t R__v = b.ReadVersion(0, 0);
02686 b.ClassBegin(TSQLFile::Class(), R__v);
02687
02688 b.ClassMember("CreateTime","TString");
02689 sbuf.Streamer(b);
02690 TDatime timeC(sbuf.Data());
02691 fDatimeC = timeC;
02692
02693 b.ClassMember("ModifyTime","TString");
02694 sbuf.Streamer(b);
02695 TDatime timeM(sbuf.Data());
02696 fDatimeM = timeM;
02697
02698 b.ClassMember("UUID","TString");
02699 sbuf.Streamer(b);
02700 TUUID id(sbuf.Data());
02701 fUUID = id;
02702
02703 b.ClassEnd(TSQLFile::Class());
02704 } else {
02705
02706 b.WriteVersion(TSQLFile::Class());
02707
02708 b.ClassBegin(TSQLFile::Class());
02709
02710 b.ClassMember("CreateTime","TString");
02711 sbuf = fDatimeC.AsSQLString();
02712 sbuf.Streamer(b);
02713
02714 b.ClassMember("ModifyTime","TString");
02715 fDatimeM.Set();
02716 sbuf = fDatimeM.AsSQLString();
02717 sbuf.Streamer(b);
02718
02719 b.ClassMember("UUID","TString");
02720 sbuf = fUUID.AsString();
02721 sbuf.Streamer(b);
02722
02723 b.ClassEnd(TSQLFile::Class());
02724 }
02725 }