Logo ROOT   6.16/01
Reference Guide
TSQLFile.cxx
Go to the documentation of this file.
1// @(#)root/sql:$Id: 6f6608219c30ddefdf8e25d7cf170d5e69704cd3 $
2// Author: Sergey Linev 20/11/2005
3
4/*************************************************************************
5 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13\class TSQLFile
14\ingroup IO
15
16Access an SQL db via the TFile interface.
17
18The main motivation for the TSQLFile development is to have
19"transparent" access to SQL data base via standard TFile interface.
20The main approach that each class (but not each object) has one or two tables
21with names like $(CLASSNAME)_ver$(VERSION) and $(CLASSNAME)_raw$(VERSION)
22For example: TAxis_ver8 or TList_raw5
23Second kind of tables appears, when some of class members can not be converted to
24normalized form or when class has custom streamer.
25For instance, for TH1 class two tables are required: TH1_ver4 and TH1_raw4
26Most of members are stored in TH1_ver4 table column-wise, and only member:
27 Double_t* fBuffer; //[fBufferSize]
28can not be represented as column while size of array is not fixed.
29Therefore, fBuffer will be written as list of values in TH1_raw4 table.
30All objects, stored in the DB, will be registered in table "ObjectsTable".
31In this there are following columns:
32| Name | Description |
33|------|-------------|
34| "key:id" | key identifier to which belong object |
35| "obj:id" | object identifier |
36| "Class" | object class name |
37| "Version" | object class version |
38
39 Data in each "ObjectsTable" row uniquely identify, in which table
40 and which column object is stored.
41
42In normal situation all class data should be sorted column-wise.
43Up to now following member are supported:
44 -# Basic data types. Here is everything clear. Column SQL type will be as much as possible
45 close to the original type of value.
46 -# Fixed array of basic data types. In this case n columns like fArr[0],
47 fArr[1] and so on will be created.
48 If there is multidimensional array, names will be fArr2[1][2][1] and so on
49 -# Parent class. In this case version of parent class is stored and
50 data of parent class will be stored with the same obj:id in correspondent table.
51 There is a special case, when parent store nothing (this is for instance TQObject).
52 In that case just -1 is written to avoid any extra checks if table exist or not.
53 -# Object as data member. In that case object is saved in normal way to data base and column
54 will contain id of this object.
55 -# Pointer on object. Same as before. In case if object was already stored, just its id
56 will be placed in the column. For NULL pointer 0 is used.
57 -# TString. Now column with limited width like VARCAHR(255) in MySQL is used.
58 Later this will be improved to support maximum possible strings
59 -# Anything else. Data will be converted to raw format and saved in _streamer_ table.
60 Each row supplied with obj:id and row:id, where row:id indicates
61 data, corresponding to this particular data member, and column
62 will contain this raw:id
63
64All conversion to SQL statements are done with help of TSQLStructure class.
65This is special hierarchical structure wich internally is very similar
66to XML structures. TBufferSQL2 creates these structures, when object
67data is streamed by ROOT and only afterwards all SQL statements will be produced
68and applied all together.
69When data is reading, TBufferSQL2 will produce requests to database
70during unstreaming of object data.
71Optionally (default this options on) name of column includes
72suffix which indicates type of column. For instance:
73| Name | Description |
74|------|-------------|
75| *:parent | parent class, column contain class version |
76| *:object | other object, column contain object id |
77| *:rawdata | raw data, column contains id of raw data from _streamer_ table |
78| *:Int_t | column with integer value |
79
80Use TSQLFile::SetUseSuffixes(kFALSE) to disable suffixes usage.
81This and several other options can be changed only when
82TSQLFile created with options "CREATE" or "RECREATE" and only before
83first write operation. These options are:
84| Name | Description |
85|------|-------------|
86| SetUseSuffixes() | suffix usage in column names (default - on) |
87| SetArrayLimit() | defines maximum array size, which can has column for each element (default 21) |
88| SetTablesType() | table type name in MySQL database (default "InnoDB") |
89| SetUseIndexes() | usage of indexes in database (default kIndexesBasic) |
90
91Normally these functions should be called immediately after TSQLFile constructor.
92When objects data written to database, by default START TRANSACTION/COMMIT
93SQL commands are used before and after data storage. If TSQLFile detects
94any problems, ROLLBACK command will be used to restore
95previous state of data base. If transactions not supported by SQL server,
96they can be disabled by SetUseTransactions(kTransactionsOff). Or user
97can take responsibility to use transactions function himself.
98By default only indexes for basic tables are created.
99In most cases usage of indexes increase performance to data reading,
100but it also can increase time of writing data to database.
101There are several modes of index usage available in SetUseIndexes() method
102There is MakeSelectQuery(TClass*) method, which
103produces SELECT statement to get objects data of specified class.
104Difference from simple statement like:
105 mysql> SELECT * FROM TH1I_ver1
106that not only data for that class, but also data from parent classes
107will be extracted from other tables and combined in single result table.
108Such select query can be useful for external access to objects data.
109
110Up to now MySQL 4.1 and Oracle 9i were tested.
111Some extra work is required for other SQL databases.
112Hopefully, this should be straightforward.
113
114Known problems and open questions.
115 -# TTree is not supported by TSQLFile. There is independent development
116 of TTreeSQL class, which allows to store trees directly in SQL database
117 -# TClonesArray is store objects in raw format,
118 which can not be accessed outside ROOT.
119 This will be changed later.
120 -# TDirectory cannot work. Hopefully, will (changes in ROOT basic I/O is required)
121 -# Streamer infos are not written to file, therefore schema evolution
122 is not yet supported. All eforts are done to enable this feature in
123 the near future
124
125### Example how TSQLFile can be used
126
127#### A session saving data to a SQL data base
128~~~{.cpp}
129auto dbname = "mysql://host.domain:3306/dbname";
130auto username = "username";
131auto userpass = "userpass";
132
133// Clean data base and create primary tables
134auto f = new TSQLFile(dbname, "recreate", username, userpass);
135// Write with standard I/O functions
136arr->Write("arr", TObject::kSingleKey);
137h1->Write("histo");
138// Close connection to DB
139delete f;
140~~~
141
142#### A session read data from SQL data base
143~~~{.cpp}
144// Open database again in read-only mode
145auto f = new TSQLFile(dbname, "open", username, userpass);
146// Show list of keys
147f->ls();
148// Read stored object, again standard ROOT I/O
149auto h1 = (TH1*) f->Get("histo");
150if (h1!=0) { h1->SetDirectory(0); h1->Draw(); }
151auto obj = f->Get("arr");
152if (obj!=0) obj->Print("*");
153// close connection to DB
154delete f;
155~~~
156
157The "SQL I/O" package is currently under development.
158Any bug reports and suggestions are welcome.
159Author: S.Linev, GSI Darmstadt, S.Linev@gsi.de
160*/
161
162#include "TSQLFile.h"
163
164#include "TROOT.h"
165#include "TSystem.h"
166#include "TList.h"
167#include "TBrowser.h"
168#include "TObjArray.h"
169#include "TObjString.h"
170#include "TList.h"
171#include "TArrayC.h"
172#include "TVirtualStreamerInfo.h"
173#include "TStreamerElement.h"
174#include "TProcessID.h"
175#include "TError.h"
176#include "TClass.h"
177
178#include "TSQLServer.h"
179#include "TSQLTableInfo.h"
180#include "TSQLColumnInfo.h"
181#include "TSQLStatement.h"
182#include "TSQLResult.h"
183#include "TSQLRow.h"
184#include "TBufferSQL2.h"
185#include "TSQLStructure.h"
186#include "TKeySQL.h"
187#include "TSQLClassInfo.h"
188#include "TSQLObjectData.h"
189#include "TVirtualMutex.h"
190
191#include "Riostream.h"
192
194
195const char *mysql_BasicTypes[21] = {"VARCHAR(255)", // kBase = 0, used for text
196 "TINYINT UNSIGNED", // kChar = 1,
197 "SMALLINT", // kShort = 2,
198 "INT", // kInt = 3,
199 "BIGINT", // kLong = 4,
200 "FLOAT", // kFloat = 5,
201 "INT", // kCounter = 6,
202 "VARCHAR(255)", // kCharStar = 7,
203 "DOUBLE", // kDouble = 8,
204 "DOUBLE", // kDouble32= 9,
205 "", // nothing
206 "TINYINT UNSIGNED", // kUChar = 11,
207 "SMALLINT UNSIGNED", // kUShort = 12,
208 "INT UNSIGNED", // kUInt = 13,
209 "BIGINT UNSIGNED", // kULong = 14,
210 "INT UNSIGNED", // kBits = 15,
211 "BIGINT", // kLong64 = 16,
212 "BIGINT UNSIGNED", // kULong64 = 17,
213 "BOOL", // kBool = 18,
214 "DOUBLE", // kFloat16 = 19,
215 ""};
216
217const char *mysql_OtherTypes[13] = {
218 "VARCHAR(255)", // smallest text
219 "255", // maximum length of small text
220 "TEXT", // biggest size text
221 "DATETIME", // date & time
222 "`", // quote for identifier like table name or column name
223 "dir:id", // dir id column
224 "key:id", // key id column
225 "obj:id", // object id column
226 "raw:id", // raw data id column
227 "str:id", // string id column
228 ":", // name separator between name and type like TObject:Parent
229 "\"", // quote for string values in MySQL
230 "InnoDB" // default tables types, used only for MySQL tables
231};
232
233const char *oracle_BasicTypes[21] = {"VARCHAR(255)", // kBase = 0, used for text
234 "INT", // kChar = 1,
235 "INT", // kShort = 2,
236 "INT", // kInt = 3,
237 "INT", // kLong = 4,
238 "FLOAT", // kFloat = 5,
239 "INT", // kCounter = 6,
240 "VARCHAR(255)", // kCharStar = 7,
241 "DOUBLE PRECISION", // kDouble = 8,
242 "DOUBLE PRECISION", // kDouble32= 9,
243 "", // nothing
244 "INT", // kUChar = 11,
245 "INT", // kUShort = 12,
246 "INT", // kUInt = 13,
247 "INT", // kULong = 14,
248 "INT", // kBits = 15,
249 "INT", // kLong64 = 16,
250 "INT", // kULong64 = 17,
251 "INT", // kBool = 18,
252 "FLOAT", // kFloat16 = 19,
253 ""};
254
255const char *oracle_OtherTypes[13] = {
256 "VARCHAR(1000)", // smallest text
257 "1000", // maximum size of smallest text
258 "VARCHAR(4000)", // biggest size text, CLOB is not yet supported by TOracleRow
259 "VARCHAR(50)", // date & time
260 "\"", // quote for identifier like table name or column name
261 "dir:id", // dir id column
262 "key:id", // key id column
263 "obj:id", // object id column
264 "raw:id", // raw data id column
265 "str:id", // string id column
266 ":", // name separator between name and type like TObject:parent
267 "'", // quote for string values in Oracle
268 "" // default tables types, used only for MySQL tables
269};
270
271////////////////////////////////////////////////////////////////////////////////
272/// default TSQLFile constructor
273
275 : TFile(), fSQL(0), fSQLClassInfos(0), fUseSuffixes(kTRUE), fSQLIOversion(1), fArrayLimit(21),
276 fCanChangeConfig(kFALSE), fTablesType(), fUseTransactions(0), fUseIndexes(0), fModifyCounter(0), fQuerisCounter(0),
277 fBasicTypes(0), fOtherTypes(0), fUserName(), fLogFile(0), fIdsTableExists(kFALSE), fStmtCounter(0)
278{
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// Connects to SQL server with provided arguments.
284///
285/// If the constructor fails in any way IsZombie() will
286/// return true. Use IsOpen() to check if the file is (still) open.
287/// | Option | Description |
288/// |--------|-------------|
289/// | NEW or CREATE | Create a ROOT tables in database if the tables already exists connection is not opened.|
290/// | RECREATE | Create completely new tables. Any existing table will be deleted.|
291/// | UPDATE | Open an existing database for writing. If data base open by other TSQLFile instance for writing,
292/// write access will be rejected.|
293/// | BREAKLOCK | Special case when lock was not correctly released by TSQLFile instance. This may happen if
294/// program crashed when TSQLFile was open with write access mode.|
295/// | READ / OPEN | Open an existing data base for reading.|
296///
297/// For more details see comments for TFile::TFile() constructor.
298/// For a moment TSQLFile does not support TTree objects and subdirectories.
299
300TSQLFile::TSQLFile(const char *dbname, Option_t *option, const char *user, const char *pass)
301 : TFile(), fSQL(0), fSQLClassInfos(0), fUseSuffixes(kTRUE), fSQLIOversion(1), fArrayLimit(21),
302 fCanChangeConfig(kFALSE), fTablesType(), fUseTransactions(0), fUseIndexes(0), fModifyCounter(0), fQuerisCounter(0),
303 fBasicTypes(mysql_BasicTypes), fOtherTypes(mysql_OtherTypes), fUserName(user), fLogFile(0),
304 fIdsTableExists(kFALSE), fStmtCounter(0)
305{
306 if (!gROOT)
307 ::Fatal("TFile::TFile", "ROOT system not initialized");
308
309 gDirectory = 0;
310 SetName(dbname);
311 SetTitle("TFile interface to SQL DB");
313 fFile = this;
314
315 if (dbname && strstr(dbname, "oracle://") != 0) {
318 }
319
320 fArrayLimit = 21;
322 fUseIndexes = 1;
324
325 fD = -1;
326 fFile = this;
327 fFree = 0;
328 fVersion = gROOT->GetVersionInt(); // ROOT version in integer format
329 fUnits = 4;
330 fOption = option;
332 fWritten = 0;
333 fSumBuffer = 0;
334 fSum2Buffer = 0;
335 fBytesRead = 0;
336 fBytesWrite = 0;
337 fClassIndex = 0;
338 fSeekInfo = 0;
339 fNbytesInfo = 0;
340 fProcessIDs = 0;
341 fNProcessIDs = 0;
344
345 fOption = option;
347
348 if (fOption == "NEW")
349 fOption = "CREATE";
350
351 Bool_t breaklock = kFALSE;
352
353 if (fOption == "BREAKLOCK") {
354 breaklock = kTRUE;
355 fOption = "UPDATE";
356 }
357
358 Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
359 Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
360 Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
361 Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
362
363 if (!create && !recreate && !update && !read) {
364 read = kTRUE;
365 fOption = "READ";
366 }
367
368 if (!dbname || !dbname[0]) {
369 Error("TSQLFile", "Database not specified");
370 goto zombie;
371 }
372
373 gROOT->cd();
374
375 fSQL = TSQLServer::Connect(dbname, user, pass);
376
377 if (fSQL == 0) {
378 Error("TSQLFile", "Cannot connect to DB %s", dbname);
379 goto zombie;
380 }
381
382 if (recreate) {
383 if (IsTablesExists())
384 if (!IsWriteAccess()) {
385 Error("TSQLFile", "no write permission, DB %s locked", dbname);
386 goto zombie;
387 }
389 recreate = kFALSE;
390 create = kTRUE;
391 fOption = "CREATE";
392 }
393
394 if (create && IsTablesExists()) {
395 Error("TSQLFile", "DB tables already exists");
396 goto zombie;
397 }
398
399 if (update) {
400 if (!IsTablesExists()) {
401 update = kFALSE;
402 create = kTRUE;
403 }
404
405 if (update && !breaklock && !IsWriteAccess()) {
406 Error("TSQLFile", "no write permission, DB %s locked", dbname);
407 goto zombie;
408 }
409 }
410
411 if (read) {
412 if (!IsTablesExists()) {
413 Error("TSQLFile", "DB %s tables not exist", dbname);
414 goto zombie;
415 }
416 if (!IsReadAccess()) {
417 Error("TSQLFile", "no read permission for DB %s tables", dbname);
418 goto zombie;
419 }
420 }
421
422 fRealName = dbname;
423
424 if (create || update) {
426 if (update)
428 } else
430
431 // user can change configurations only when create (recreate) options
432 // was specified. When first object will be saved, configurations will
433 // be frozen.
434 fCanChangeConfig = create;
435
436 InitSqlDatabase(create);
437
438 return;
439
440zombie:
441
442 delete fSQL;
443 fSQL = 0;
444 MakeZombie();
446}
447
448////////////////////////////////////////////////////////////////////////////////
449/// start logging of all SQL statements in specified file
450
451void TSQLFile::StartLogFile(const char *fname)
452{
453 StopLogFile();
454 fLogFile = new std::ofstream(fname);
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// close logging file
459
461{
462 if (fLogFile != 0) {
463 delete fLogFile;
464 fLogFile = 0;
465 }
466}
467
468////////////////////////////////////////////////////////////////////////////////
469/// checks, if MySQL database
470
472{
473 if (fSQL == 0)
474 return kFALSE;
475 return strcmp(fSQL->ClassName(), "TMySQLServer") == 0;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// checks, if Oracle database
480
482{
483 if (fSQL == 0)
484 return kFALSE;
485 return strcmp(fSQL->ClassName(), "TOracleServer") == 0;
486}
487
488////////////////////////////////////////////////////////////////////////////////
489/// checks, if ODBC driver used for database connection
490
492{
493 if (fSQL == 0)
494 return kFALSE;
495 return strcmp(fSQL->ClassName(), "TODBCServer") == 0;
496}
497
498////////////////////////////////////////////////////////////////////////////////
499/// enable/disable uasge of suffixes in columns names
500/// can be changed before first object is saved into file
501
503{
504 if (!fCanChangeConfig)
505 Error("SetUseSuffixes", "Configurations already cannot be changed");
506 else
507 fUseSuffixes = on;
508}
509
510////////////////////////////////////////////////////////////////////////////////
511/// Defines maximum number of columns for array representation
512/// If array size bigger than limit, array data will be converted to raw format
513/// This is usefull to prevent tables with very big number of columns
514/// If limit==0, all arrays will be stored in raw format
515/// If limit<0, all array values will be stored in column form
516/// Default value is 21
517
519{
520 if (!fCanChangeConfig)
521 Error("SetArrayLimit", "Configurations already cannot be changed");
522 else
523 fArrayLimit = limit;
524}
525
526////////////////////////////////////////////////////////////////////////////////
527/// Defines tables type, which is used in CREATE TABLE statements
528/// Now is only used for MySQL database, where following types are supported:
529/// "BDB", "HEAP", "ISAM", "InnoDB", "MERGE", "MRG_MYISAM", "MYISAM"
530/// Default for TSQLFile is "InnoDB". For more detailes see MySQL docs.
531
532void TSQLFile::SetTablesType(const char *tables_type)
533{
534 if (!fCanChangeConfig)
535 Error("SetTablesType", "Configurations already cannot be changed");
536 else
537 fTablesType = tables_type;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Defines usage of transactions statements for writing objects data to database.
542/// | Index | Description |
543/// |-------|-------------|
544/// | kTransactionsOff=0 - no transaction operation are allowed |
545/// | kTransactionsAuto=1 - automatic mode. Each write operation, produced by TSQLFile, will be supplied by START
546/// TRANSACTION and COMMIT calls. If any error happen, ROLLBACK will returns database to previous state |
547/// | kTransactionsUser=2 - transactions are delegated to user. Methods StartTransaction(), Commit() and Rollback()
548/// should be called by user. |
549///
550/// Default UseTransactions option is kTransactionsAuto
551
553{
554 fUseTransactions = mode;
555}
556
557////////////////////////////////////////////////////////////////////////////////
558/// Start user transaction.
559///
560/// This can be usesful, when big number of objects should be stored in
561/// data base and commitment required only if all operations were successful.
562/// In that case in the end of all operations method Commit() should be
563/// called. If operation on user-level is looks like not successful,
564/// method Rollback() will return database data and TSQLFile instance to
565/// previous state.
566/// In MySQL not all tables types support transaction mode of operation.
567/// See SetTablesType() method for details .
568
570{
572 Error("SQLStartTransaction", "Only allowed when SetUseTransactions(kUserTransactions) was configured");
573 return kFALSE;
574 }
575
576 return SQLStartTransaction();
577}
578
579////////////////////////////////////////////////////////////////////////////////
580/// Commit transaction, started by StartTransaction() call.
581/// Only after that call data will be written and visible on database side.
582
584{
586 Error("SQLCommit", "Only allowed when SetUseTransactions(kUserTransactions) was configured");
587 return kFALSE;
588 }
589
590 return SQLCommit();
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Rollback all operations, done after StartTransaction() call.
595/// Database should return to initial state.
596
598{
600 Error("SQLRollback", "Only allowed when SetUseTransactions(kUserTransactions) was configured");
601 return kFALSE;
602 }
603
604 return SQLRollback();
605}
606
607////////////////////////////////////////////////////////////////////////////////
608/// Specify usage of indexes for data tables
609/// | Index | Description |
610/// |-------|-------------|
611/// | kIndexesNone = 0 | no indexes are used|
612/// | kIndexesBasic = 1 | indexes used only for keys list and objects list tables (default)|
613/// | kIndexesClass = 2 | index also created for every normal class table|
614/// | kIndexesAll = 3 | index created for every table, including _streamer_ tables|
615///
616/// Indexes in general should increase speed of access to objects data,
617/// but they required more operations and more disk space on server side
618
620{
621 if (!fCanChangeConfig)
622 Error("SetUseIndexes", "Configurations already cannot be changed");
623 else
624 fUseIndexes = use_type;
625}
626
627////////////////////////////////////////////////////////////////////////////////
628/// Return name of data base on the host
629/// For Oracle always return 0
630
631const char *TSQLFile::GetDataBaseName() const
632{
633 if (IsOracle())
634 return 0;
635 const char *name = strrchr(GetName(), '/');
636 if (name == 0)
637 return 0;
638 return name + 1;
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// Close a SQL file
643/// For more comments see TFile::Close() function
644
646{
647 if (!IsOpen())
648 return;
649
650 TString opt = option;
651 if (opt.Length() > 0)
652 opt.ToLower();
653
654 if (IsWritable()) {
657 }
658
660
661 if (fClassIndex) {
662 delete fClassIndex;
663 fClassIndex = 0;
664 }
665
666 {
667 TDirectory::TContext ctxt(this);
668 // Delete all supported directories structures from memory
670 }
671
672 // delete the TProcessIDs
673 TList pidDeleted;
674 TIter next(fProcessIDs);
675 TProcessID *pid;
676 while ((pid = (TProcessID *)next())) {
677 if (!pid->DecrementCount()) {
679 pidDeleted.Add(pid);
680 } else if (opt.Contains("r")) {
681 pid->Clear();
682 }
683 }
684 pidDeleted.Delete();
685
687 gROOT->GetListOfFiles()->Remove(this);
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// destructor of TSQLFile object
692
694{
695 Close();
696
697 if (fSQLClassInfos != 0) {
699 delete fSQLClassInfos;
700 }
701
702 StopLogFile();
703
704 if (fSQL != 0) {
705 delete fSQL;
706 fSQL = 0;
707 }
708}
709
710////////////////////////////////////////////////////////////////////////////////
711/// make private to exclude copy operator
712
714{
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// return kTRUE if file is opened and can be accessed
719
721{
722 return fSQL != 0;
723}
724
725////////////////////////////////////////////////////////////////////////////////
726/// Reopen a file with a different access mode, like from READ to
727/// See TFile::Open() for details
728
730{
731 cd();
732
733 TString opt = mode;
734 opt.ToUpper();
735
736 if (opt != "READ" && opt != "UPDATE") {
737 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
738 return 1;
739 }
740
741 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
742 return 1;
743
744 if (opt == "READ") {
745 // switch to READ mode
746
747 if (IsOpen() && IsWritable()) {
750 }
751 fOption = opt;
752
754
755 } else {
756 // switch to UPDATE mode
757
758 if (!IsWriteAccess()) {
759 Error("ReOpen", "Tables are locked, no write access");
760 return 1;
761 }
762
763 fOption = opt;
764
766
768 }
769
770 return 0;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// create SQL key, which will store object in data base
775
776TKey *TSQLFile::CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t)
777{
778 return new TKeySQL(mother, obj, name);
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// create SQL key, which will store object in data base
783
784TKey *TSQLFile::CreateKey(TDirectory *mother, const void *obj, const TClass *cl, const char *name, Int_t)
785{
786 return new TKeySQL(mother, obj, cl, name);
787}
788
789////////////////////////////////////////////////////////////////////////////////
790/// Write file info like configurations, title, UUID and other
791
793{
795}
796
797////////////////////////////////////////////////////////////////////////////////
798/// Store all TVirtualStreamerInfo, used in file, in sql database
799
801{
802 // return;
803
804 // do not write anything when no basic tables was created
805 if (!IsTablesExists())
806 return;
807
808 if (gDebug > 1)
809 Info("WriteStreamerInfo", "Saving streamer infos to database");
810
811 TList list;
812
813 TIter iter(gROOT->GetListOfStreamerInfo());
814
815 TVirtualStreamerInfo *info = 0;
816
817 while ((info = (TVirtualStreamerInfo *)iter()) != 0) {
818 Int_t uid = info->GetNumber();
819 if (fClassIndex->fArray[uid]) {
820 if (gDebug > 1)
821 Info("WriteStreamerInfo", "Add %s", info->GetName());
822 list.Add(info);
823 }
824 }
825 if (list.GetSize() == 0)
826 return;
827 fClassIndex->fArray[0] = 2; // to prevent adding classes in TVirtualStreamerInfo::TagFile
828
829 WriteSpecialObject(sqlio::Ids_StreamerInfos, &list, "StreamerInfo", "StreamerInfos of this file");
830
831 fClassIndex->fArray[0] = 0; // to prevent adding classes in TVirtualStreamerInfo::TagFile
832}
833
834////////////////////////////////////////////////////////////////////////////////
835/// write special kind of object like streamer infos or file itself
836/// keys for that objects should exist in tables but not indicated in list of keys,
837/// therefore users can not get them with TDirectoryFile::Get() method
838
839Bool_t TSQLFile::WriteSpecialObject(Long64_t keyid, TObject *obj, const char *name, const char *title)
840{
841 DeleteKeyFromDB(keyid);
842 if (obj == 0)
843 return kTRUE;
844
845 Long64_t objid = StoreObjectInTables(keyid, obj, obj->IsA());
846
847 if (objid > 0) {
848 TDatime now;
849
850 TKeySQL *key = new TKeySQL(this, keyid, objid, name, title, now.AsSQLString(), 1, obj->ClassName());
851 WriteKeyData(key);
852 delete key;
853 }
854
855 return (objid > 0);
856}
857
858////////////////////////////////////////////////////////////////////////////////
859/// Read data of special kind of objects
860
862{
863 TKeySQL *key = 0;
864
865 StreamKeysForDirectory(this, kFALSE, keyid, &key);
866 if (key == 0)
867 return obj;
868
869 TBufferSQL2 buffer(TBuffer::kRead, this);
870
871 buffer.InitMap();
872
873 TClass *cl = 0;
874
875 void *res = buffer.SqlReadAny(key->GetDBKeyId(), key->GetDBObjId(), &cl, obj);
876
877 if ((cl == TSQLFile::Class()) && (res != 0) && (obj == this)) {
878 // name should not be preserved while name of database may be changed
879 SetTitle(key->GetTitle());
880 }
881
882 delete key;
883
884 return (TObject *)res;
885}
886
887////////////////////////////////////////////////////////////////////////////////
888/// Read back streamer infos from database
889/// List of streamer infos is always stored with key:id 0,
890/// which is not shown in normal keys list
891
893{
894 // return new TList;
895
896 if (gDebug > 1)
897 Info("GetStreamerInfoList", "Start reading of streamer infos");
898
900
902
903 TList *list = dynamic_cast<TList *>(obj);
904 if (list == 0) {
905 delete obj;
906 return {nullptr, 1, hash};
907 }
908
909 return {list, 0, hash};
910}
911
912////////////////////////////////////////////////////////////////////////////////
913/// save data which is not yet in Database
914/// Typically this is streamerinfos structures or
915
917{
918 if (fSQL == 0)
919 return;
920
922 WriteHeader();
923}
924
925////////////////////////////////////////////////////////////////////////////////
926/// read keys for specified directory (when update == kFALSE)
927/// or update value for modified keys when update == kTRUE
928/// Returns number of successfully read keys or -1 if error
929
930Int_t TSQLFile::StreamKeysForDirectory(TDirectory *dir, Bool_t doupdate, Long64_t specialkeyid, TKeySQL **specialkey)
931{
932 if (dir == 0)
933 return -1;
934
935 const char *quote = SQLIdentifierQuote();
936
937 Long64_t dirid = dir->GetSeekDir();
938
939 TString sqlcmd;
940 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::KeysTable, quote, quote, SQLDirIdColumn(), quote,
941 dirid);
942 if (specialkeyid >= 0) {
943 TString buf;
944 buf.Form(" AND %s%s%s=%lld", quote, SQLKeyIdColumn(), quote, specialkeyid);
945 sqlcmd += buf;
946 }
947
948 TSQLResult *res = SQLQuery(sqlcmd.Data(), 2);
949
950 if (res == 0)
951 return -1;
952
953 Int_t nkeys = 0;
954
955 TSQLRow *row = 0;
956
957 while ((row = res->Next()) != 0) {
958 nkeys++;
959
960 Long64_t keyid = sqlio::atol64((*row)[0]);
961 // Int_t dirid = atoi((*row)[1]);
962 Long64_t objid = sqlio::atol64((*row)[2]);
963 const char *keyname = (*row)[3];
964 const char *keytitle = (*row)[4];
965 const char *keydatime = (*row)[5];
966 Int_t cycle = atoi((*row)[6]);
967 const char *classname = (*row)[7];
968
969 if (gDebug > 4)
970 std::cout << " Reading keyid = " << keyid << " name = " << keyname << std::endl;
971
972 if ((keyid >= sqlio::Ids_FirstKey) || (keyid == specialkeyid)) {
973 if (doupdate) {
974 TKeySQL *key = FindSQLKey(dir, keyid);
975
976 if (key == 0) {
977 Error("StreamKeysForDirectory", "Key with id %lld not exist in list", keyid);
978 nkeys = -1; // this will finish execution
979 } else if (key->IsKeyModified(keyname, keytitle, keydatime, cycle, classname))
980 UpdateKeyData(key);
981
982 } else {
983 TKeySQL *key = new TKeySQL(dir, keyid, objid, keyname, keytitle, keydatime, cycle, classname);
984 if (specialkey != 0) {
985 *specialkey = key;
986 nkeys = 1;
987 } else
988 dir->GetListOfKeys()->Add(key);
989 }
990 }
991 delete row;
992 }
993
994 delete res;
995
996 if (gDebug > 4) {
997 Info("StreamKeysForDirectory", "dir = %s numread = %d", dir->GetName(), nkeys);
998 dir->GetListOfKeys()->Print("*");
999 }
1000
1001 return nkeys;
1002}
1003
1004////////////////////////////////////////////////////////////////////////////////
1005/// initialize sql database and correspondent structures
1006/// identical to TFile::Init() function
1007
1009{
1010 Int_t len = gROOT->GetListOfStreamerInfo()->GetSize() + 1;
1011 if (len < 5000)
1012 len = 5000;
1013 fClassIndex = new TArrayC(len);
1014 fClassIndex->Reset(0);
1015
1016 if (!create) {
1017
1019
1020 // read data corresponding to TSQLFile
1021 if (ok) {
1023
1025
1026 ok = (ReadSpecialObject(sqlio::Ids_TSQLFile, this) != 0);
1027 }
1028
1029 // read list of keys
1030 if (ok)
1031 ok = StreamKeysForDirectory(this, kFALSE) >= 0;
1032
1033 if (!ok) {
1034 Error("InitSqlDatabase", "Cannot detect proper tabled in database. Close.");
1035 Close();
1036 delete fSQL;
1037 fSQL = 0;
1038 MakeZombie();
1039 gDirectory = gROOT;
1040 return;
1041 }
1042 }
1043
1044 {
1046 gROOT->GetListOfFiles()->Add(this);
1047 }
1048 cd();
1049
1050 fNProcessIDs = 0;
1051 TKey *key = 0;
1052 TIter iter(fKeys);
1053 while ((key = (TKey *)iter()) != 0) {
1054 if (!strcmp(key->GetClassName(), "TProcessID"))
1055 fNProcessIDs++;
1056 }
1057
1059}
1060
1061////////////////////////////////////////////////////////////////////////////////
1062/// read table configurations as special table
1063
1065{
1066 const char *quote = SQLIdentifierQuote();
1067
1068 TString sqlcmd;
1069 sqlcmd.Form("SELECT * FROM %s%s%s", quote, sqlio::ConfigTable, quote);
1070 TSQLResult *res = SQLQuery(sqlcmd.Data(), 2);
1071
1072 if (res == 0)
1073 return kFALSE;
1074
1075 // should be found, otherwise will be error
1076 fSQLIOversion = 0;
1077
1078 Int_t lock = 0;
1079
1080#define ReadIntCfg(name, target) \
1081 if ((field.CompareTo(name, TString::kIgnoreCase) == 0)) \
1082 target = value.Atoi(); \
1083 else
1084
1085#define ReadBoolCfg(name, target) \
1086 if ((field.CompareTo(name, TString::kIgnoreCase) == 0)) \
1087 target = value.CompareTo(sqlio::True, TString::kIgnoreCase) == 0; \
1088 else
1089
1090#define ReadStrCfg(name, target) \
1091 if ((field.CompareTo(name, TString::kIgnoreCase) == 0)) \
1092 target = value; \
1093 else
1094
1095 TSQLRow *row = 0;
1096
1097 while ((row = res->Next()) != 0) {
1098
1099 TString field = row->GetField(0);
1100 TString value = row->GetField(1);
1101
1102 delete row;
1103
1108 {
1109 Error("ReadConfigurations", "Invalid configuration field %s", field.Data());
1110 fSQLIOversion = 0;
1111 break;
1112 }
1113 }
1114 (void)lock;
1115
1116 delete res;
1117
1118 return (fSQLIOversion > 0);
1119}
1120
1121////////////////////////////////////////////////////////////////////////////////
1122/// Creates initial tables in database
1123/// This is table with configurations and table with keys
1124/// Function called once when first object is stored to the file.
1125
1127{
1128 TString sqlcmd;
1129
1130 const char *quote = SQLIdentifierQuote();
1131 const char *vquote = SQLValueQuote();
1132
1134 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::ConfigTable, quote);
1135 SQLQuery(sqlcmd.Data());
1136 }
1137
1138 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s)", quote, sqlio::ConfigTable, quote, quote, sqlio::CT_Field,
1139 quote, SQLSmallTextType(), quote, sqlio::CT_Value, quote, SQLSmallTextType());
1140 if ((fTablesType.Length() > 0) && IsMySQL()) {
1141 sqlcmd += " ENGINE=";
1142 sqlcmd += fTablesType;
1143 }
1144
1145 SQLQuery(sqlcmd.Data());
1146
1147#define WrintCfg(name, type, value) \
1148 { \
1149 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s%s%s, %s" type "%s)", quote, sqlio::ConfigTable, quote, vquote, name, \
1150 vquote, vquote, value, vquote); \
1151 SQLQuery(sqlcmd.Data()); \
1152 }
1153
1162
1163 // from this moment on user cannot change configurations
1165
1167 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::KeysTable, quote);
1168 SQLQuery(sqlcmd.Data());
1169 }
1170
1171 sqlcmd.Form(
1172 "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)",
1173 quote, sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote, SQLIntType(), quote, SQLDirIdColumn(), quote,
1174 SQLIntType(), quote, SQLObjectIdColumn(), quote, SQLIntType(), quote, sqlio::KT_Name, quote, SQLSmallTextType(),
1175 quote, sqlio::KT_Title, quote, SQLSmallTextType(), quote, sqlio::KT_Datetime, quote, SQLDatetimeType(), quote,
1176 sqlio::KT_Cycle, quote, SQLIntType(), quote, sqlio::KT_Class, quote, SQLSmallTextType());
1177
1178 if ((fTablesType.Length() > 0) && IsMySQL()) {
1179 sqlcmd += " ENGINE=";
1180 sqlcmd += fTablesType;
1181 }
1182
1183 SQLQuery(sqlcmd.Data());
1184
1185 if (GetUseIndexes() > kIndexesNone) {
1186 sqlcmd.Form("CREATE UNIQUE INDEX %s%s%s ON %s%s%s (%s%s%s)", quote, sqlio::KeysTableIndex, quote, quote,
1187 sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote);
1188 SQLQuery(sqlcmd.Data());
1189 }
1190}
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// Update value of modify counter in config table
1194/// Modify counter used to indicate that something was changed in database.
1195/// It will be used when multiple instances of TSQLFile for the same data base
1196/// will be connected.
1197
1199{
1200 if (!IsWritable()) {
1201 Error("IncrementModifyCounter", "Cannot update tables without write accsess");
1202 return;
1203 }
1204
1205 TString sqlcmd;
1206 const char *quote = SQLIdentifierQuote();
1207 const char *vquote = SQLValueQuote();
1208
1209 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%d WHERE %s%s%s=%s%s%s", quote, sqlio::ConfigTable, quote, quote,
1210 sqlio::CT_Value, quote, ++fModifyCounter, quote, sqlio::CT_Field, quote, vquote,
1211 sqlio::cfg_ModifyCounter, vquote);
1212 SQLQuery(sqlcmd.Data());
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// Produce \b SELECT statement which can be used to get all data
1217/// of class cl in one \b SELECT statement.
1218///
1219/// This statement also can be used to create \b VIEW by command like
1220/// mysql> CREATE VIEW TH1I_view AS $CLASSSELECT$
1221/// Where \b $CLASSSELECT$ argument should be produced by call
1222/// f->MakeSelectQuery(TH1I::Class());
1223/// \b VIEWs supported by latest MySQL 5 and Oracle
1224
1226{
1227 TString res = "";
1228 TSQLClassInfo *sqlinfo = FindSQLClassInfo(cl);
1229 if (sqlinfo == 0)
1230 return res;
1231
1232 TString columns, tables;
1233 Int_t tablecnt = 0;
1234
1235 if (!ProduceClassSelectQuery(cl->GetStreamerInfo(), sqlinfo, columns, tables, tablecnt))
1236 return res;
1237
1238 res.Form("SELECT %s FROM %s", columns.Data(), tables.Data());
1239
1240 return res;
1241}
1242
1243////////////////////////////////////////////////////////////////////////////////
1244/// used by MakeClassSelectQuery method to add columns from table of
1245/// class, specified by TVirtualStreamerInfo structure
1246
1248 TString &tables, Int_t &tablecnt)
1249{
1250 if ((info == 0) || (sqlinfo == 0))
1251 return kFALSE;
1252
1253 if (!sqlinfo->IsClassTableExist())
1254 return kFALSE;
1255
1256 const char *quote = SQLIdentifierQuote();
1257
1258 TString table_syn;
1259 table_syn.Form("t%d", ++tablecnt);
1260
1261 Bool_t start = tables.Length() == 0;
1262
1263 TString buf;
1264
1265 if (start)
1266 buf.Form("%s AS %s", sqlinfo->GetClassTableName(), table_syn.Data());
1267 else
1268 buf.Form(" LEFT JOIN %s AS %s USING(%s%s%s)", sqlinfo->GetClassTableName(), table_syn.Data(), quote,
1269 SQLObjectIdColumn(), quote);
1270
1271 tables += buf;
1272
1273 if (start)
1274 columns.Form("%s.%s%s%s", table_syn.Data(), quote, SQLObjectIdColumn(), quote);
1275
1276 if (info->GetClass() == TObject::Class()) {
1277 buf.Form(", %s.%s", table_syn.Data(), sqlio::TObjectUniqueId);
1278 columns += buf;
1279 buf.Form(", %s.%s", table_syn.Data(), sqlio::TObjectBits);
1280 columns += buf;
1281 buf.Form(", %s.%s", table_syn.Data(), sqlio::TObjectProcessId);
1282 columns += buf;
1283 return kTRUE;
1284 }
1285
1286 TIter iter(info->GetElements());
1287 TStreamerElement *elem = 0;
1288
1289 while ((elem = (TStreamerElement *)iter()) != 0) {
1290 Int_t coltype = TSQLStructure::DefineElementColumnType(elem, this);
1291 TString colname = TSQLStructure::DefineElementColumnName(elem, this);
1292
1293 buf = "";
1294 switch (coltype) {
1295
1300 buf.Form(", %s.%s%s%s", table_syn.Data(), quote, colname.Data(), quote);
1301 columns += buf;
1302 break;
1303 }
1304
1306 TClass *parentcl = elem->GetClassPointer();
1307 ProduceClassSelectQuery(parentcl->GetStreamerInfo(), FindSQLClassInfo(parentcl), columns, tables, tablecnt);
1308 break;
1309 }
1310
1312 for (Int_t n = 0; n < elem->GetArrayLength(); n++) {
1313 colname = TSQLStructure::DefineElementColumnName(elem, this, n);
1314 buf.Form(", %s.%s%s%s", table_syn.Data(), quote, colname.Data(), quote);
1315 columns += buf;
1316 }
1317 break;
1318 }
1319 } // switch
1320 }
1321
1322 return (columns.Length() > 0) && (tables.Length() > 0);
1323}
1324
1325////////////////////////////////////////////////////////////////////////////////
1326/// Checks if main keys table is existing
1327
1329{
1331}
1332
1333////////////////////////////////////////////////////////////////////////////////
1334/// Checkis, if lock is free in configuration tables
1335
1337{
1338 return GetLocking() == kLockFree;
1339}
1340
1341////////////////////////////////////////////////////////////////////////////////
1342/// Set locking mode for current database
1343
1345{
1346 TString sqlcmd;
1347 const char *quote = SQLIdentifierQuote();
1348 const char *vquote = SQLValueQuote();
1349
1350 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%d WHERE %s%s%s=%s%s%s", quote, sqlio::ConfigTable, quote, quote,
1351 sqlio::CT_Value, quote, mode, quote, sqlio::CT_Field, quote, vquote, sqlio::cfg_LockingMode, vquote);
1352 SQLQuery(sqlcmd.Data());
1353}
1354
1355////////////////////////////////////////////////////////////////////////////////
1356/// Return current locking mode for that file
1357
1359{
1360 const char *quote = SQLIdentifierQuote();
1361 const char *vquote = SQLValueQuote();
1362
1363 TString sqlcmd;
1364 sqlcmd.Form("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s=%s%s%s", quote, sqlio::CT_Value, quote, quote,
1365 sqlio::ConfigTable, quote, quote, sqlio::CT_Field, quote, vquote, sqlio::cfg_LockingMode, vquote);
1366
1367 TSQLResult *res = SQLQuery(sqlcmd.Data(), 1);
1368 TSQLRow *row = (res == 0) ? 0 : res->Next();
1369 TString field = (row == 0) ? "" : row->GetField(0);
1370 delete row;
1371 delete res;
1372
1373 if (field.Length() == 0)
1374 return kLockFree;
1375
1376 return field.Atoi();
1377}
1378
1379////////////////////////////////////////////////////////////////////////////////
1380/// dummy, in future should check about read access to database
1381
1383{
1384 return kTRUE;
1385}
1386
1387////////////////////////////////////////////////////////////////////////////////
1388/// Submits query to SQL server.
1389///
1390/// | Flag Value | Effect|
1391/// |------------|-------|
1392/// | 0 | result is not interesting and will be deleted|
1393/// | 1 | return result of submitted query
1394/// | 2 | results is may be necessary for long time Oracle plugin do not support working with several TSQLResult
1395/// objects, therefore explicit deep copy will be produced|
1396///
1397/// If ok!=0, it will contains kTRUE is Query was successfull, otherwise kFALSE
1398
1399TSQLResult *TSQLFile::SQLQuery(const char *cmd, Int_t flag, Bool_t *ok)
1400{
1401 if (fLogFile != 0)
1402 *fLogFile << cmd << std::endl;
1403
1404 if (ok != 0)
1405 *ok = kFALSE;
1406
1407 if (fSQL == 0)
1408 return 0;
1409
1410 if (gDebug > 2)
1411 Info("SQLQuery", "%s", cmd);
1412
1414
1415 if (flag == 0) {
1416 Bool_t res = fSQL->Exec(cmd);
1417 if (ok != 0)
1418 *ok = res;
1419 return 0;
1420 }
1421
1422 TSQLResult *res = fSQL->Query(cmd);
1423 if (ok != 0)
1424 *ok = res != 0;
1425 if (res == 0)
1426 return 0;
1427 // if ((flag==2) && IsOracle())
1428 // res = new TSQLResultCopy(res);
1429 return res;
1430}
1431
1432////////////////////////////////////////////////////////////////////////////////
1433/// Test if DB support statement and number of open statements is not exceeded
1434
1436{
1437 if (fSQL == 0)
1438 return kFALSE;
1439
1440 if (!fSQL->HasStatement())
1441 return kFALSE;
1442
1443 return kTRUE; // !IsOracle() || (fStmtCounter<15);
1444}
1445
1446////////////////////////////////////////////////////////////////////////////////
1447/// Produces SQL statement for currently conected DB server
1448
1450{
1451 if (fSQL == 0)
1452 return 0;
1453
1454 if (!fSQL->HasStatement())
1455 return 0;
1456
1457 if (gDebug > 1)
1458 Info("SQLStatement", "%s", cmd);
1459
1460 fStmtCounter++;
1461 fQuerisCounter++; // one statement counts as one query
1462
1463 return fSQL->Statement(cmd, bufsize);
1464}
1465
1466////////////////////////////////////////////////////////////////////////////////
1467/// delete statement and decrease counter
1468
1470{
1471 if (stmt == 0)
1472 return;
1473
1474 fStmtCounter--;
1475
1476 delete stmt;
1477}
1478
1479////////////////////////////////////////////////////////////////////////////////
1480/// supplies set of commands to server
1481/// Commands is stored as array of TObjString
1482
1484{
1485 if ((cmds == 0) || (fSQL == 0))
1486 return kFALSE;
1487
1488 Bool_t ok = kTRUE;
1489 TIter iter(cmds);
1490 TObject *cmd = 0;
1491 while ((cmd = iter()) != 0) {
1492 SQLQuery(cmd->GetName(), 0, &ok);
1493 if (!ok)
1494 break;
1495 }
1496
1497 return ok;
1498}
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// Test, if table of specified name exists
1502
1503Bool_t TSQLFile::SQLTestTable(const char *tablename)
1504{
1505 if (fSQL == 0)
1506 return kFALSE;
1507
1508 if (fSQL->HasTable(tablename))
1509 return kTRUE;
1510
1511 TString buf(tablename);
1512 buf.ToLower();
1513 if (fSQL->HasTable(buf.Data()))
1514 return kTRUE;
1515 buf.ToUpper();
1516 return fSQL->HasTable(buf.Data());
1517}
1518
1519////////////////////////////////////////////////////////////////////////////////
1520/// Returns maximum value, found in specified columnname of table tablename
1521/// Column type should be numeric
1522
1523Long64_t TSQLFile::SQLMaximumValue(const char *tablename, const char *columnname)
1524{
1525 if (fSQL == 0)
1526 return -1;
1527
1528 if (gDebug > 2)
1529 Info("SQLMaximumValue", "Requests for %s column %s", tablename, columnname);
1530
1531 const char *quote = SQLIdentifierQuote();
1532
1533 TString query;
1534 query.Form("SELECT MAX(%s%s%s) FROM %s%s%s", quote, columnname, quote, quote, tablename, quote);
1535 TSQLResult *res = SQLQuery(query.Data(), 1);
1536
1537 if (res == 0)
1538 return -1;
1539
1540 TSQLRow *row = res->Next();
1541
1542 Long64_t maxid = -1;
1543 if (row != 0)
1544 if (row->GetField(0) != 0)
1545 maxid = sqlio::atol64(row->GetField(0));
1546
1547 delete row;
1548 delete res;
1549
1550 if (gDebug > 2)
1551 Info("SQLMaximumValue", "Result = %lld", maxid);
1552 ;
1553
1554 return maxid;
1555}
1556
1557////////////////////////////////////////////////////////////////////////////////
1558/// Delete all tables in database
1559
1561{
1562 if (fSQL == 0)
1563 return;
1564
1565 TList *tables = fSQL->GetTablesList();
1566 if (tables == 0)
1567 return;
1568
1569 TString sqlcmd;
1570 const char *quote = SQLIdentifierQuote();
1571
1572 TIter iter(tables);
1573 TObject *obj = 0;
1574 while ((obj = iter()) != 0) {
1575 sqlcmd.Form("DROP TABLE %s%s%s", quote, obj->GetName(), quote);
1576 SQLQuery(sqlcmd.Data());
1577 }
1578 delete tables;
1579}
1580
1581////////////////////////////////////////////////////////////////////////////////
1582/// Start SQL transaction.
1583
1585{
1586 return fSQL ? fSQL->StartTransaction() : kFALSE;
1587}
1588
1589////////////////////////////////////////////////////////////////////////////////
1590/// Commit SQL transaction
1591
1593{
1594 return fSQL ? fSQL->Commit() : kFALSE;
1595}
1596
1597////////////////////////////////////////////////////////////////////////////////
1598/// Rollback all SQL operations, done after start transaction
1599
1601{
1602 return fSQL ? fSQL->Rollback() : kFALSE;
1603}
1604
1605////////////////////////////////////////////////////////////////////////////////
1606/// returns maximum allowed length of identifiers
1607
1609{
1610 Int_t maxlen = fSQL == 0 ? 32 : fSQL->GetMaxIdentifierLength();
1611
1612 // lets exclude absolute ubnormal data
1613 if (maxlen < 10)
1614 maxlen = 10;
1615
1616 return maxlen;
1617}
1618
1619////////////////////////////////////////////////////////////////////////////////
1620/// Remove key with specified id from keys table
1621/// also removes all objects data, related to this table
1622
1624{
1625 if (!IsWritable() || (keyid < 0) || (fSQL == 0))
1626 return;
1627
1628 TString sqlcmd;
1629 const char *quote = SQLIdentifierQuote();
1630
1631 sqlcmd.Form("SELECT MIN(%s%s%s), MAX(%s%s%s) FROM %s%s%s WHERE %s%s%s=%lld", quote, SQLObjectIdColumn(), quote,
1632 quote, SQLObjectIdColumn(), quote, quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote,
1633 keyid);
1634 TSQLResult *res = SQLQuery(sqlcmd.Data(), 2);
1635 TSQLRow *row = res == 0 ? 0 : res->Next();
1636 Long64_t minid(1), maxid(0);
1637
1638 if ((row != 0) && (row->GetField(0) != 0) && (row->GetField(1) != 0)) {
1639 minid = sqlio::atol64(row->GetField(0));
1640 maxid = sqlio::atol64(row->GetField(1));
1641 }
1642
1643 delete row;
1644 delete res;
1645
1646 // can be that object tables does not include any entry this that keyid
1647 if (minid <= maxid) {
1648 TIter iter(fSQLClassInfos);
1649 TSQLClassInfo *info = 0;
1650 TString querymask, query;
1651 querymask.Form("DELETE FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld", quote, "%s", quote, quote,
1652 SQLObjectIdColumn(), quote, minid, maxid);
1653
1654 while ((info = (TSQLClassInfo *)iter()) != 0) {
1655
1656 if (info->IsClassTableExist()) {
1657 query.Form(querymask.Data(), info->GetClassTableName());
1658 SQLQuery(query.Data());
1659 }
1660
1661 if (info->IsRawTableExist()) {
1662 query.Form(querymask.Data(), info->GetRawTableName());
1663 SQLQuery(query.Data());
1664 }
1665 }
1666 }
1667
1668 sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(),
1669 quote, keyid);
1670 SQLQuery(sqlcmd.Data());
1671
1672 sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote,
1673 keyid);
1674 SQLQuery(sqlcmd.Data());
1675
1677}
1678
1679////////////////////////////////////////////////////////////////////////////////
1680/// Search for TKeySQL object with specified keyid
1681
1683{
1684 if (dir == 0)
1685 return 0;
1686
1687 TIter next(dir->GetListOfKeys());
1688 TObject *obj = 0;
1689
1690 while ((obj = next()) != 0) {
1691 TKeySQL *key = dynamic_cast<TKeySQL *>(obj);
1692 if (key != 0)
1693 if (key->GetDBKeyId() == keyid)
1694 return key;
1695 }
1696
1697 return 0;
1698}
1699
1700////////////////////////////////////////////////////////////////////////////////
1701/// Add entry into keys table
1702
1704{
1705 if ((fSQL == 0) || (key == 0))
1706 return kFALSE;
1707
1708 if (!IsTablesExists())
1710
1711 TString sqlcmd;
1712 const char *valuequote = SQLValueQuote();
1713 const char *quote = SQLIdentifierQuote();
1714
1715 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %lld, %lld, %s%s%s, %s%s%s, %s%s%s, %d, %s%s%s)", quote,
1716 sqlio::KeysTable, quote, key->GetDBKeyId(), key->GetDBDirId(), key->GetDBObjId(), valuequote,
1717 key->GetName(), valuequote, valuequote, key->GetTitle(), valuequote, valuequote,
1718 key->GetDatime().AsSQLString(), valuequote, key->GetCycle(), valuequote, key->GetClassName(),
1719 valuequote);
1720
1721 Bool_t ok = kTRUE;
1722
1723 SQLQuery(sqlcmd.Data(), 0, &ok);
1724
1725 if (ok)
1727
1728 return ok;
1729}
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// Updates (overwrites) key data in KeysTable
1733
1735{
1736 if ((fSQL == 0) || (key == 0))
1737 return kFALSE;
1738
1739 TString sqlcmd;
1740 const char *valuequote = SQLValueQuote();
1741 const char *quote = SQLIdentifierQuote();
1742
1743 TString keyname = key->GetName();
1744 TString keytitle = key->GetTitle();
1745 TString keydatime = key->GetDatime().AsSQLString();
1746
1747 TSQLStructure::AddStrBrackets(keyname, valuequote);
1748 TSQLStructure::AddStrBrackets(keytitle, valuequote);
1749 TSQLStructure::AddStrBrackets(keydatime, valuequote);
1750
1751 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", quote,
1752 sqlio::KeysTable, quote, quote, sqlio::KT_Name, quote, keyname.Data(), quote, sqlio::KT_Title, quote,
1753 keytitle.Data(), quote, sqlio::KT_Datetime, quote, keydatime.Data(), quote, sqlio::KT_Cycle, quote,
1754 key->GetCycle(), quote, SQLKeyIdColumn(), quote, key->GetDBKeyId());
1755
1756 Bool_t ok = kTRUE;
1757
1758 SQLQuery(sqlcmd.Data(), 0, &ok);
1759
1760 if (ok)
1762
1763 return ok;
1764}
1765
1766////////////////////////////////////////////////////////////////////////////////
1767/// Returns next possible key identifier
1768
1770{
1771 Long64_t max = -1;
1772
1775
1776 if (max < 0)
1777 return sqlio::Ids_FirstKey;
1778
1779 return max + 1;
1780}
1781
1782////////////////////////////////////////////////////////////////////////////////
1783/// Return (if exists) TSQLClassInfo for specified class name and version
1784
1786{
1787 if (fSQLClassInfos == 0)
1788 return 0;
1789
1790 TIter iter(fSQLClassInfos);
1791 TSQLClassInfo *info = 0;
1792
1793 while ((info = (TSQLClassInfo *)iter()) != 0) {
1794 if (strcmp(info->GetName(), clname) == 0)
1795 if (info->GetClassVersion() == version)
1796 return info;
1797 }
1798 return 0;
1799}
1800
1801////////////////////////////////////////////////////////////////////////////////
1802/// return (if exists) TSQLClassInfo for specified class
1803
1805{
1806 return FindSQLClassInfo(cl->GetName(), cl->GetClassVersion());
1807}
1808
1809////////////////////////////////////////////////////////////////////////////////
1810/// Search in database tables for specified class and return TSQLClassInfo object
1811
1813{
1814 TSQLClassInfo *info = FindSQLClassInfo(clname, version);
1815 if (info != 0)
1816 return info;
1817
1818 if (fSQL == 0)
1819 return 0;
1820
1821 Long64_t maxid = 0;
1822
1823 if (fSQLClassInfos != 0) {
1824 TIter iter(fSQLClassInfos);
1825 info = 0;
1826 while ((info = (TSQLClassInfo *)iter()) != 0) {
1827 if (info->GetClassId() > maxid)
1828 maxid = info->GetClassId();
1829 }
1830 }
1831
1832 info = new TSQLClassInfo(maxid + 1, clname, version);
1833
1834 info->SetClassTableName(DefineTableName(clname, version, kFALSE));
1835 info->SetRawTableName(DefineTableName(clname, version, kTRUE));
1836
1837 if (fSQLClassInfos == 0)
1838 fSQLClassInfos = new TList;
1839 fSQLClassInfos->Add(info);
1840
1841 return info;
1842}
1843
1844////////////////////////////////////////////////////////////////////////////////
1845/// Proposes table name for class
1846
1847TString TSQLFile::DefineTableName(const char *clname, Int_t version, Bool_t rawtable)
1848{
1849 Int_t maxlen = SQLMaxIdentifierLength();
1850
1851 TString res;
1852
1853 const char *suffix = rawtable ? "_raw" : "_ver";
1854
1855 res.Form("%s%s%d", clname, suffix, version);
1856
1857 if ((res.Length() <= maxlen) && !HasTable(res.Data()))
1858 return res;
1859
1860 TString scnt;
1861
1862 Int_t len = strlen(clname);
1863 Int_t cnt = version;
1864 if (cnt > 100)
1865 cnt = 0; // do not start with the biggest values
1866
1867 do {
1868 scnt.Form("%d%s", cnt, suffix);
1869 Int_t numlen = scnt.Length();
1870 if (numlen >= maxlen - 2)
1871 break;
1872
1873 res = clname;
1874
1875 if (len + numlen > maxlen)
1876 res.Resize(maxlen - numlen);
1877
1878 res += scnt;
1879
1880 if (!HasTable(res.Data()))
1881 return res;
1882
1883 cnt++;
1884
1885 } while (cnt < 10000);
1886
1887 Error("DefineTableName", "Cannot produce table name for class %s ver %d", clname, version);
1888 res.Form("%s%s%d", clname, suffix, version);
1889
1890 return res;
1891}
1892
1893////////////////////////////////////////////////////////////////////////////////
1894/// Test if table name exists
1895
1897{
1898 if (fSQLClassInfos == 0)
1899 return kFALSE;
1900
1901 TIter iter(fSQLClassInfos);
1902 TSQLClassInfo *info = 0;
1903 while ((info = (TSQLClassInfo *)iter()) != 0) {
1904 if (strcmp(info->GetClassTableName(), name) == 0)
1905 return kTRUE;
1906 if (strcmp(info->GetRawTableName(), name) == 0)
1907 return kTRUE;
1908 }
1909
1910 return kFALSE;
1911}
1912
1913////////////////////////////////////////////////////////////////////////////////
1914/// Search in database tables for specified class and return TSQLClassInfo object
1915
1917{
1918 return RequestSQLClassInfo(cl->GetName(), cl->GetClassVersion());
1919}
1920
1921////////////////////////////////////////////////////////////////////////////////
1922/// Read all class infos from IdsTable
1923
1925{
1926 if (fSQL == 0)
1927 return;
1928
1930
1931 if (!fIdsTableExists)
1932 return;
1933
1934 TString sqlcmd;
1935 const char *quote = SQLIdentifierQuote();
1936
1937 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s", quote, sqlio::IdsTable, quote, quote,
1939
1940 TSQLResult *res = SQLQuery(sqlcmd.Data(), 1);
1941
1942 TSQLRow *row = 0;
1943
1944 if (res != 0)
1945 while ((row = res->Next()) != 0) {
1946 Long64_t tableid = sqlio::atol64(row->GetField(0));
1947 Int_t version = atoi(row->GetField(1));
1948
1949 const char *classname = row->GetField(3);
1950 const char *classtable = row->GetField(4);
1951
1952 TSQLClassInfo *info = new TSQLClassInfo(tableid, classname, version);
1953 info->SetClassTableName(classtable);
1954
1955 if (fSQLClassInfos == 0)
1956 fSQLClassInfos = new TList;
1957 fSQLClassInfos->Add(info);
1958
1959 delete row;
1960 }
1961 delete res;
1962
1963 TIter next(fSQLClassInfos);
1964 TSQLClassInfo *info = 0;
1965
1966 while ((info = (TSQLClassInfo *)next()) != 0) {
1967 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %lld ORDER BY %s%s%s", quote, sqlio::IdsTable, quote, quote,
1968 sqlio::IT_TableID, quote, info->GetClassId(), quote, sqlio::IT_SubID, quote);
1969 res = SQLQuery(sqlcmd.Data(), 1);
1970
1971 TObjArray *cols = 0;
1972
1973 if (res != 0)
1974 while ((row = res->Next()) != 0) {
1975
1976 Int_t typ = atoi(row->GetField(2));
1977
1978 const char *fullname = row->GetField(3);
1979 const char *sqlname = row->GetField(4);
1980 const char *info2 = row->GetField(5);
1981
1982 if (typ == TSQLStructure::kIdColumn) {
1983 if (cols == 0)
1984 cols = new TObjArray;
1985 cols->Add(new TSQLClassColumnInfo(fullname, sqlname, info2));
1986 }
1987
1988 delete row;
1989 }
1990
1991 delete res;
1992
1993 info->SetColumns(cols);
1994 }
1995
1996 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s", quote, sqlio::IdsTable, quote, quote,
1998
1999 res = SQLQuery(sqlcmd.Data(), 1);
2000
2001 if (res != 0)
2002 while ((row = res->Next()) != 0) {
2003 Long64_t tableid = sqlio::atol64(row->GetField(0));
2004 Int_t version = atoi(row->GetField(1));
2005
2006 const char *classname = row->GetField(3);
2007 const char *rawtable = row->GetField(4);
2008
2009 TSQLClassInfo *info2 = FindSQLClassInfo(classname, version);
2010
2011 if (info2 == 0) {
2012 info2 = new TSQLClassInfo(tableid, classname, version);
2013
2014 if (fSQLClassInfos == 0)
2015 fSQLClassInfos = new TList;
2016 fSQLClassInfos->Add(info2);
2017 }
2018
2019 info2->SetRawTableName(rawtable);
2020 info2->SetRawExist(kTRUE);
2021
2022 delete row;
2023 }
2024
2025 delete res;
2026}
2027
2028////////////////////////////////////////////////////////////////////////////////
2029/// Add entry into IdsTable, where all tables names and columns names are listed
2030
2031void TSQLFile::AddIdEntry(Long64_t tableid, Int_t subid, Int_t type, const char *name, const char *sqlname,
2032 const char *info)
2033{
2034 if ((fSQL == 0) || !IsWritable())
2035 return;
2036
2037 TString sqlcmd;
2038 const char *valuequote = SQLValueQuote();
2039 const char *quote = SQLIdentifierQuote();
2040
2041 if (!fIdsTableExists) {
2042
2044 sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::IdsTable, quote);
2045 SQLQuery(sqlcmd.Data());
2046 }
2047
2048 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)", quote,
2049 sqlio::IdsTable, quote, quote, sqlio::IT_TableID, quote, SQLIntType(), quote, sqlio::IT_SubID, quote,
2050 SQLIntType(), quote, sqlio::IT_Type, quote, SQLIntType(), quote, sqlio::IT_FullName, quote,
2051 SQLSmallTextType(), quote, sqlio::IT_SQLName, quote, SQLSmallTextType(), quote, sqlio::IT_Info, quote,
2053 if ((fTablesType.Length() > 0) && IsMySQL()) {
2054 sqlcmd += " ENGINE=";
2055 sqlcmd += fTablesType;
2056 }
2057 SQLQuery(sqlcmd.Data());
2058
2060 }
2061
2062 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %d, %d, %s%s%s, %s%s%s, %s%s%s)", quote, sqlio::IdsTable, quote,
2063 tableid, subid, type, valuequote, name, valuequote, valuequote, sqlname, valuequote, valuequote, info,
2064 valuequote);
2065
2066 SQLQuery(sqlcmd.Data());
2067}
2068
2069////////////////////////////////////////////////////////////////////////////////
2070/// Create normal class table if required
2071
2073{
2074 if (sqlinfo == 0)
2075 return kFALSE;
2076
2077 // this is normal situation, when no extra column infos was created when not necessary
2078 if (colinfos == 0)
2079 return sqlinfo->IsClassTableExist();
2080
2081 if (sqlinfo->IsClassTableExist()) {
2082 if (colinfos != 0) {
2083 colinfos->Delete();
2084 delete colinfos;
2085 // Error("CreateClassTable","Why colinfos for table %s", sqlinfo->GetClassTableName());
2086 }
2087 return kTRUE;
2088 }
2089
2090 if (gDebug > 2)
2091 Info("CreateClassTable", "cl:%s", sqlinfo->GetName());
2092
2093 const char *quote = SQLIdentifierQuote();
2094
2095 AddIdEntry(sqlinfo->GetClassId(), sqlinfo->GetClassVersion(), TSQLStructure::kIdTable, sqlinfo->GetName(),
2096 sqlinfo->GetClassTableName(), "Main class table");
2097
2098 TString sqlcmd;
2099 sqlcmd.Form("CREATE TABLE %s%s%s (", quote, sqlinfo->GetClassTableName(), quote);
2100
2101 TIter iter(colinfos);
2103 Bool_t first = kTRUE;
2104 Bool_t forcequote = IsOracle();
2105 Int_t colid = 0;
2106 while ((col = (TSQLClassColumnInfo *)iter()) != 0) {
2107 if (!first)
2108 sqlcmd += ", ";
2109 else
2110 first = false;
2111
2112 const char *colname = col->GetSQLName();
2113 if ((strpbrk(colname, "[:.]<>") != 0) || forcequote) {
2114 sqlcmd += quote;
2115 sqlcmd += colname;
2116 sqlcmd += quote;
2117 sqlcmd += " ";
2118 } else {
2119 sqlcmd += colname, sqlcmd += " ";
2120 }
2121
2122 sqlcmd += col->GetSQLType();
2123
2124 AddIdEntry(sqlinfo->GetClassId(), colid++, TSQLStructure::kIdColumn, col->GetName(), col->GetSQLName(),
2125 col->GetSQLType());
2126 }
2127 sqlcmd += ")";
2128
2129 if ((fTablesType.Length() > 0) && IsMySQL()) {
2130 sqlcmd += " ENGINE=";
2131 sqlcmd += fTablesType;
2132 }
2133
2134 SQLQuery(sqlcmd.Data());
2135
2136 sqlinfo->SetColumns(colinfos);
2137
2138 if (GetUseIndexes() > kIndexesBasic) {
2139
2140 TString indxname = sqlinfo->GetClassTableName();
2141 indxname.ReplaceAll("_ver", "_i1x");
2142
2143 sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I1%s ON %s%s%s (%s%s%s)", quote, indxname.Data(), quote, quote,
2144 sqlinfo->GetClassTableName(), quote, quote, SQLObjectIdColumn(), quote);
2145 SQLQuery(sqlcmd.Data());
2146 }
2147
2148 return kTRUE;
2149}
2150
2151////////////////////////////////////////////////////////////////////////////////
2152/// Create the raw table
2153
2155{
2156 if (sqlinfo == 0)
2157 return kFALSE;
2158
2159 if (sqlinfo->IsRawTableExist())
2160 return kTRUE;
2161
2162 const char *quote = SQLIdentifierQuote();
2163
2164 if (gDebug > 2)
2165 Info("CreateRawTable", "%s", sqlinfo->GetName());
2166
2167 TString sqlcmd;
2168
2169 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)", quote, sqlinfo->GetRawTableName(), quote,
2170 quote, SQLObjectIdColumn(), quote, SQLIntType(), quote, SQLRawIdColumn(), quote, SQLIntType(),
2172
2173 if ((fTablesType.Length() > 0) && IsMySQL()) {
2174 sqlcmd += " ENGINE=";
2175 sqlcmd += fTablesType;
2176 }
2177
2178 SQLQuery(sqlcmd.Data());
2179 sqlinfo->SetRawExist(kTRUE);
2180
2181 if (GetUseIndexes() > kIndexesClass) {
2182 TString indxname = sqlinfo->GetClassTableName();
2183 indxname.ReplaceAll("_ver", "_i2x");
2184
2185 sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I2%s ON %s%s%s (%s%s%s, %s%s%s)", quote, indxname.Data(), quote, quote,
2186 sqlinfo->GetRawTableName(), quote, quote, SQLObjectIdColumn(), quote, quote, SQLRawIdColumn(), quote);
2187 SQLQuery(sqlcmd.Data());
2188 }
2189
2190 AddIdEntry(sqlinfo->GetClassId(), sqlinfo->GetClassVersion(), TSQLStructure::kIdRawTable, sqlinfo->GetName(),
2191 sqlinfo->GetRawTableName(), "Raw data class table");
2192
2193 return kTRUE;
2194}
2195
2196////////////////////////////////////////////////////////////////////////////////
2197/// Checks that table for big strings is exists
2198/// If not, will be created
2199
2201{
2202 if (fSQL == 0)
2203 return kFALSE;
2204
2206 return kTRUE;
2207
2208 const char *quote = SQLIdentifierQuote();
2209
2210 TString sqlcmd;
2211 sqlcmd.Form("CREATE TABLE %s (%s%s%s %s, %s%s%s %s, %s %s)", sqlio::StringsTable, quote, SQLObjectIdColumn(), quote,
2213
2214 if (fTablesType.Length() > 0) {
2215 sqlcmd += " ENGINE=";
2216 sqlcmd += fTablesType;
2217 }
2218
2219 SQLQuery(sqlcmd.Data());
2220
2221 return kTRUE;
2222}
2223
2224////////////////////////////////////////////////////////////////////////////////
2225/// Produces id which will be placed in column instead of string itself
2226
2228{
2229 TString res;
2230 res.Form("%s %lld %s %d %s", sqlio::LongStrPrefix, objid, sqlio::LongStrPrefix, strid, sqlio::LongStrPrefix);
2231 return res;
2232}
2233
2234////////////////////////////////////////////////////////////////////////////////
2235/// Checks if this is long string code
2236/// returns 0, if not or string id
2237
2239{
2240 if (value == 0)
2241 return 0;
2242 if (strlen(value) < strlen(sqlio::LongStrPrefix) * 3 + 6)
2243 return 0;
2244 if (strstr(value, sqlio::LongStrPrefix) != value)
2245 return 0;
2246
2247 value += strlen(sqlio::LongStrPrefix);
2248 if (*value++ != ' ')
2249 return 0;
2250 TString s_strid, s_objid;
2251 if ((*value < '1') || (*value > '9'))
2252 return 0;
2253 do {
2254 s_objid.Append(*value++);
2255 } while ((*value != 0) && (*value >= '0') && (*value <= '9'));
2256
2257 if (*value++ != ' ')
2258 return 0;
2259 if ((*value == 0) || (strstr(value, sqlio::LongStrPrefix) != value))
2260 return 0;
2261 value += strlen(sqlio::LongStrPrefix);
2262 if (*value++ != ' ')
2263 return 0;
2264
2265 if ((*value < '1') || (*value > '9'))
2266 return 0;
2267 do {
2268 s_strid.Append(*value++);
2269 } while ((*value != 0) && (*value >= '0') && (*value <= '9'));
2270 if (*value++ != ' ')
2271 return 0;
2272
2273 if ((*value == 0) || (strcmp(value, sqlio::LongStrPrefix) != 0))
2274 return 0;
2275
2276 Long64_t objid2 = sqlio::atol64(s_objid.Data());
2277 if (objid2 != objid)
2278 return 0;
2279
2280 return atoi(s_strid.Data());
2281}
2282
2283////////////////////////////////////////////////////////////////////////////////
2284/// Returns value of string, extracted from special table,
2285/// where long strings are stored
2286
2288{
2290 return kFALSE;
2291
2292 TString cmd;
2293 const char *quote = SQLIdentifierQuote();
2294 cmd.Form("SELECT %s FROM %s%s%s WHERE %s%s%s=%lld AND %s%s%s=%d", sqlio::ST_Value, quote, sqlio::StringsTable, quote,
2295 quote, SQLObjectIdColumn(), quote, objid, quote, SQLStrIdColumn(), quote, strid);
2296
2297 TSQLResult *res = SQLQuery(cmd.Data(), 1);
2298 if (res == 0)
2299 return kFALSE;
2300 TSQLRow *row = res->Next();
2301 if (row == 0) {
2302 delete res;
2303 return kFALSE;
2304 }
2305 value = row->GetField(0);
2306
2307 delete row;
2308 delete res;
2309
2310 return kTRUE;
2311}
2312
2313////////////////////////////////////////////////////////////////////////////////
2314/// Checks that objects table is exists
2315/// If not, table will be created
2316/// Returns maximum value for existing objects id
2317
2319{
2320 if (fSQL == 0)
2321 return -1;
2322
2323 Long64_t maxid = -1;
2324
2325 if (gDebug > 2)
2326 Info("VerifyObjectTable", "Checks if object table is there");
2327
2330 else {
2331 TString sqlcmd;
2332 const char *quote = SQLIdentifierQuote();
2333 sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)", quote, sqlio::ObjectsTable, quote,
2334 quote, SQLKeyIdColumn(), quote, SQLIntType(), quote, SQLObjectIdColumn(), quote, SQLIntType(), quote,
2335 sqlio::OT_Class, quote, SQLSmallTextType(), quote, sqlio::OT_Version, quote, SQLIntType());
2336
2337 if ((fTablesType.Length() > 0) && IsMySQL()) {
2338 sqlcmd += " ENGINE=";
2339 sqlcmd += fTablesType;
2340 }
2341
2342 SQLQuery(sqlcmd.Data());
2343
2344 if (GetUseIndexes() > kIndexesNone) {
2345 sqlcmd.Form("CREATE UNIQUE INDEX %s%s%s ON %s%s%s (%s%s%s)", quote, sqlio::ObjectsTableIndex, quote, quote,
2346 sqlio::ObjectsTable, quote, quote, SQLObjectIdColumn(), quote);
2347 SQLQuery(sqlcmd.Data());
2348 }
2349 }
2350
2351 return maxid;
2352}
2353
2354////////////////////////////////////////////////////////////////////////////////
2355/// Read from objects table data for specified objectid
2356
2358{
2359 if (fSQL == 0)
2360 return kFALSE;
2361
2362 TString sqlcmd;
2363 const char *quote = SQLIdentifierQuote();
2364 sqlcmd.Form("SELECT %s%s%s, %s%s%s FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::OT_Class, quote, quote,
2365 sqlio::OT_Version, quote, quote, sqlio::ObjectsTable, quote, quote, SQLObjectIdColumn(), quote, objid);
2366 TSQLResult *res = SQLQuery(sqlcmd.Data(), 1);
2367 if (res == 0)
2368 return kFALSE;
2369 TSQLRow *row = res->Next();
2370 if (row != 0) {
2371 clname = row->GetField(0);
2372 version = atoi(row->GetField(1));
2373 }
2374
2375 delete row;
2376 delete res;
2377 return row != 0;
2378}
2379
2380////////////////////////////////////////////////////////////////////////////////
2381/// Produce array of TSQLObjectInfo objects for all objects, belong to that key
2382/// Array should be deleted by calling function afterwards
2383
2385{
2386 if (fSQL == 0)
2387 return 0;
2388
2389 TString sqlcmd;
2390 const char *quote = SQLIdentifierQuote();
2391 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", quote,
2392 SQLObjectIdColumn(), quote, quote, sqlio::OT_Class, quote, quote, sqlio::OT_Version, quote, quote,
2393 sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, keyid, quote, SQLObjectIdColumn(), quote);
2394
2395 TObjArray *arr = 0;
2396
2397 if (fLogFile != 0)
2398 *fLogFile << sqlcmd << std::endl;
2399 if (gDebug > 2)
2400 Info("SQLObjectsInfo", "%s", sqlcmd.Data());
2402
2403 TSQLStatement *stmt = SQLStatement(sqlcmd.Data(), 1000);
2404
2405 if (stmt != 0) {
2406 stmt->Process();
2407 stmt->StoreResult();
2408
2409 while (stmt->NextResultRow()) {
2410 Long64_t objid = stmt->GetLong64(0);
2411 const char *clname = stmt->GetString(1);
2412 Int_t version = stmt->GetInt(2);
2413
2414 TSQLObjectInfo *info = new TSQLObjectInfo(objid, clname, version);
2415 if (arr == 0)
2416 arr = new TObjArray();
2417 arr->Add(info);
2418 }
2419
2420 delete stmt;
2421 return arr;
2422 }
2423
2424 TSQLResult *res = SQLQuery(sqlcmd.Data(), 1);
2425 if (res == 0)
2426 return 0;
2427
2428 TSQLRow *row = 0;
2429 while ((row = res->Next()) != 0) {
2430 Long64_t objid = atoi(row->GetField(0));
2431 const char *clname = row->GetField(1);
2432 Int_t version = atoi(row->GetField(2));
2433
2434 TSQLObjectInfo *info = new TSQLObjectInfo(objid, clname, version);
2435 if (arr == 0)
2436 arr = new TObjArray();
2437 arr->Add(info);
2438
2439 delete row;
2440 }
2441 delete res;
2442 return arr;
2443}
2444
2445////////////////////////////////////////////////////////////////////////////////
2446/// Method return request result for specified objid from normal classtable
2447
2449{
2450 if (!sqlinfo->IsClassTableExist())
2451 return 0;
2452 TString sqlcmd;
2453 const char *quote = SQLIdentifierQuote();
2454 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlinfo->GetClassTableName(), quote, quote,
2455 SQLObjectIdColumn(), quote, objid);
2456 return SQLQuery(sqlcmd.Data(), 2);
2457}
2458
2459////////////////////////////////////////////////////////////////////////////////
2460/// Return data for several objects from the range from normal class table
2461
2463{
2464 if (!sqlinfo->IsClassTableExist())
2465 return 0;
2466 TString sqlcmd;
2467 const char *quote = SQLIdentifierQuote();
2468 sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld ORDER BY %s%s%s", quote,
2469 sqlinfo->GetClassTableName(), quote, quote, SQLObjectIdColumn(), quote, minobjid, maxobjid, quote,
2470 SQLObjectIdColumn(), quote);
2471 return SQLQuery(sqlcmd.Data(), 2);
2472}
2473
2474////////////////////////////////////////////////////////////////////////////////
2475/// Method return request results for specified objid from _streamer_ classtable
2476
2478{
2479 if (!sqlinfo->IsRawTableExist())
2480 return 0;
2481 TString sqlcmd;
2482 const char *quote = SQLIdentifierQuote();
2483 sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", sqlio::BT_Field, sqlio::BT_Value, quote,
2484 sqlinfo->GetRawTableName(), quote, quote, SQLObjectIdColumn(), quote, objid, quote, SQLRawIdColumn(),
2485 quote);
2486 return SQLQuery(sqlcmd.Data(), 2);
2487}
2488
2489////////////////////////////////////////////////////////////////////////////////
2490/// Method return request results for specified objid from _streamer_ classtable
2491/// Data returned in form of statement, where direct access to values are possible
2492
2494{
2495 if (!sqlinfo->IsRawTableExist())
2496 return 0;
2497
2498 TString sqlcmd;
2499 const char *quote = SQLIdentifierQuote();
2500 sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", sqlio::BT_Field, sqlio::BT_Value, quote,
2501 sqlinfo->GetRawTableName(), quote, quote, SQLObjectIdColumn(), quote, objid, quote, SQLRawIdColumn(),
2502 quote);
2503
2504 if (fLogFile != 0)
2505 *fLogFile << sqlcmd << std::endl;
2506 if (gDebug > 2)
2507 Info("BuildStatement", "%s", sqlcmd.Data());
2509
2510 TSQLStatement *stmt = SQLStatement(sqlcmd.Data(), 1000);
2511 if (stmt == 0)
2512 return 0;
2513
2514 stmt->Process();
2515
2516 stmt->StoreResult();
2517
2518 return stmt;
2519}
2520
2521////////////////////////////////////////////////////////////////////////////////
2522/// Store object in database. Return stored object id or -1 if error
2523
2524Long64_t TSQLFile::StoreObjectInTables(Long64_t keyid, const void *obj, const TClass *cl)
2525{
2526 if (fSQL == 0)
2527 return -1;
2528
2529 Long64_t objid = VerifyObjectTable();
2530 if (objid <= 0)
2531 objid = 1;
2532 else
2533 objid++;
2534
2535 TBufferSQL2 buffer(TBuffer::kWrite, this);
2536
2537 buffer.InitMap();
2538
2539 TSQLStructure *s = buffer.SqlWriteAny(obj, cl, objid);
2540
2541 if ((buffer.GetErrorFlag() > 0) && s) {
2542 Error("StoreObjectInTables", "Cannot convert object data to TSQLStructure");
2543 objid = -1;
2544 } else {
2545 TObjArray cmds;
2546 // here tables may be already created, therefore
2547 // it should be protected by transactions operations
2548 if (s && !s->ConvertToTables(this, keyid, &cmds)) {
2549 Error("StoreObjectInTables", "Cannot convert to SQL statements");
2550 objid = -1;
2551 } else {
2552 Bool_t needcommit = kFALSE;
2553
2556 needcommit = kTRUE;
2557 }
2558
2559 if (!SQLApplyCommands(&cmds)) {
2560 Error("StoreObject", "Cannot correctly store object data in database");
2561 objid = -1;
2562 if (needcommit)
2563 SQLRollback();
2564 } else {
2565 if (needcommit)
2566 SQLCommit();
2567 }
2568 }
2569 cmds.Delete();
2570 }
2571
2572 return objid;
2573}
2574
2575////////////////////////////////////////////////////////////////////////////////
2576/// Returns sql type name which is most closer to ROOT basic type.
2577/// typ should be from TVirtualStreamerInfo:: constansts like TVirtualStreamerInfo::kInt
2578
2580{
2581 return (typ < 0) || (typ > 18) ? 0 : fBasicTypes[typ];
2582}
2583
2584////////////////////////////////////////////////////////////////////////////////
2585/// return SQL integer type
2586
2587const char *TSQLFile::SQLIntType() const
2588{
2590}
2591
2592////////////////////////////////////////////////////////////////////////////////
2593/// Create entry for directory in database
2594
2596{
2597 TDirectory *mother = dir->GetMotherDir();
2598 if (mother == 0)
2599 mother = this;
2600
2601 // key will be added to mother directory
2602 TKeySQL *key = new TKeySQL(mother, dir, dir->GetName(), dir->GetTitle());
2603
2604 return key->GetDBKeyId();
2605}
2606
2607////////////////////////////////////////////////////////////////////////////////
2608/// Read directory list of keys from database
2609
2611{
2612 // First delete all old keys
2613 dir->GetListOfKeys()->Delete();
2614
2615 if (gDebug > 2)
2616 Info("DirReadKeys", "dir = %s id = %lld", dir->GetName(), dir->GetSeekDir());
2617
2618 return StreamKeysForDirectory(dir, kFALSE);
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Write directory keys list to database
2623
2625{
2627}
2628
2629////////////////////////////////////////////////////////////////////////////////
2630/// Update dir header in the file
2631
2633{
2634 TSQLClassInfo *sqlinfo = FindSQLClassInfo("TDirectory", TDirectoryFile::Class()->GetClassVersion());
2635 if (sqlinfo == 0)
2636 return;
2637
2638 // try to identify key with data for our directory
2639 TKeySQL *key = FindSQLKey(dir->GetMotherDir(), dir->GetSeekDir());
2640 if (key == 0)
2641 return;
2642
2643 const char *valuequote = SQLValueQuote();
2644 const char *quote = SQLIdentifierQuote();
2645
2646 TString timeC = fDatimeC.AsSQLString();
2647 TSQLStructure::AddStrBrackets(timeC, valuequote);
2648
2649 TString timeM = fDatimeM.AsSQLString();
2650 TSQLStructure::AddStrBrackets(timeM, valuequote);
2651
2652 TString uuid = dir->GetUUID().AsString();
2653 TSQLStructure::AddStrBrackets(uuid, valuequote);
2654
2655 TString sqlcmd;
2656
2657 TString col1name = "CreateTime";
2658 TString col2name = "ModifyTime";
2659 TString col3name = "UUID";
2660 if (GetUseSuffixes()) {
2661 col1name += sqlio::StrSuffix;
2662 col2name += sqlio::StrSuffix;
2663 col3name += sqlio::StrSuffix;
2664 }
2665
2666 sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s WHERE %s%s%s=%lld", quote,
2667 sqlinfo->GetClassTableName(), quote, quote, col1name.Data(), quote, timeC.Data(), quote, col2name.Data(),
2668 quote, timeM.Data(), quote, col3name.Data(), quote, uuid.Data(), quote, SQLObjectIdColumn(), quote,
2669 key->GetDBObjId());
2670
2671 SQLQuery(sqlcmd.Data());
2672}
2673
2674////////////////////////////////////////////////////////////////////////////////
2675/// Streamer for TSQLFile class.
2676/// Stores only data for TDirectory.
2677
2678void TSQLFile::Streamer(TBuffer &b)
2679{
2680
2681 TString sbuf;
2682
2683 if (b.IsReading()) {
2684 Version_t R__v = b.ReadVersion(0, 0);
2685 b.ClassBegin(TSQLFile::Class(), R__v);
2686
2687 b.ClassMember("CreateTime", "TString");
2688 sbuf.Streamer(b);
2689 TDatime timeC(sbuf.Data());
2690 fDatimeC = timeC;
2691
2692 b.ClassMember("ModifyTime", "TString");
2693 sbuf.Streamer(b);
2694 TDatime timeM(sbuf.Data());
2695 fDatimeM = timeM;
2696
2697 b.ClassMember("UUID", "TString");
2698 sbuf.Streamer(b);
2699 TUUID id(sbuf.Data());
2700 fUUID = id;
2701
2702 b.ClassEnd(TSQLFile::Class());
2703 } else {
2704
2705 b.WriteVersion(TSQLFile::Class());
2706
2707 b.ClassBegin(TSQLFile::Class());
2708
2709 b.ClassMember("CreateTime", "TString");
2710 sbuf = fDatimeC.AsSQLString();
2711 sbuf.Streamer(b);
2712
2713 b.ClassMember("ModifyTime", "TString");
2714 fDatimeM.Set();
2715 sbuf = fDatimeM.AsSQLString();
2716 sbuf.Streamer(b);
2717
2718 b.ClassMember("UUID", "TString");
2719 sbuf = fUUID.AsString();
2720 sbuf.Streamer(b);
2721
2722 b.ClassEnd(TSQLFile::Class());
2723 }
2724}
void Class()
Definition: Class.C:29
#define b(i)
Definition: RSha256.hxx:100
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
#define gDirectory
Definition: TDirectory.h:213
int type
Definition: TGX11.cxx:120
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
#define gROOT
Definition: TROOT.h:410
const char * mysql_OtherTypes[13]
Definition: TSQLFile.cxx:217
const char * oracle_BasicTypes[21]
Definition: TSQLFile.cxx:233
#define ReadStrCfg(name, target)
#define ReadBoolCfg(name, target)
#define ReadIntCfg(name, target)
const char * mysql_BasicTypes[21]
Definition: TSQLFile.cxx:195
#define WrintCfg(name, type, value)
const char * oracle_OtherTypes[13]
Definition: TSQLFile.cxx:255
typedef void((*Func_t)())
#define R__LOCKGUARD(mutex)
Array of chars or bytes (8 bits per element).
Definition: TArrayC.h:27
Char_t * fArray
Definition: TArrayC.h:30
void Reset(Char_t val=0)
Definition: TArrayC.h:47
virtual void InitMap()
Create the fMap container and initialize them with the null object.
Definition: TBufferIO.cxx:129
Converts data to SQL statements or read data from SQL tables.
Definition: TBufferSQL2.h:29
Int_t GetErrorFlag() const
Definition: TBufferSQL2.h:134
TSQLStructure * SqlWriteAny(const void *obj, const TClass *cl, Long64_t objid)
Convert object of any class to sql structures Return pointer on created TSQLStructure TSQLStructure o...
void * SqlReadAny(Long64_t keyid, Long64_t objid, TClass **cl, void *obj=nullptr)
Recreate object from sql structure.
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
@ kWrite
Definition: TBuffer.h:70
@ kRead
Definition: TBuffer.h:70
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4452
Version_t GetClassVersion() const
Definition: TClass.h:391
virtual void Print(Option_t *option="") const
Default print for collections, calls Print(option, 1).
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * AsSQLString() const
Return the date & time in SQL compatible string format, like: 1997-01-15 20:16:28.
Definition: TDatime.cxx:151
void Set()
Set Date/Time to current time as reported by the system.
Definition: TDatime.cxx:288
TFile * fFile
Pointer to current file in memory.
void SetWritable(Bool_t writable=kTRUE)
Set the new value of fWritable recursively.
TDatime fDatimeM
Date and time of last modification.
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Long64_t fSeekDir
Location of directory on file.
TDatime fDatimeC
Date and time when directory is created.
Bool_t fWritable
True if directory is writable.
Bool_t IsWritable() const
TList * fKeys
Pointer to keys list in memory.
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual Long64_t GetSeekDir() const
Definition: TDirectory.h:155
virtual void SetName(const char *newname)
Set the name for directory If the directory name is changed after the directory was written once,...
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:150
TUUID fUUID
Definition: TDirectory.h:88
TUUID GetUUID() const
Definition: TDirectory.h:160
virtual TDirectory * GetMotherDir() const
Definition: TDirectory.h:152
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
Long64_t fBytesRead
Number of bytes read from this file.
Definition: TFile.h:71
Double_t fSum2Buffer
Sum of squares of buffer sizes of objects written so far.
Definition: TFile.h:69
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition: TFile.cxx:3498
TArrayC * fClassIndex
!Index of TStreamerInfo classes written to this file
Definition: TFile.h:89
Long64_t fSeekInfo
Location on disk of StreamerInfo record.
Definition: TFile.h:76
virtual void SetCompressionLevel(Int_t level=ROOT::RCompressionSetting::ELevel::kUseMin)
See comments for function SetCompressionSettings.
Definition: TFile.cxx:2218
Int_t fVersion
File format version.
Definition: TFile.h:78
Int_t fNbytesInfo
Number of bytes for StreamerInfo record.
Definition: TFile.h:81
TString fOption
File options.
Definition: TFile.h:86
Int_t fD
File descriptor.
Definition: TFile.h:77
Char_t fUnits
Number of bytes for file pointers.
Definition: TFile.h:87
TObjArray * fProcessIDs
!Array of pointers to TProcessIDs
Definition: TFile.h:90
Long64_t fBytesWrite
Number of bytes written to this file.
Definition: TFile.h:70
TList * fFree
Free segments linked list table.
Definition: TFile.h:88
TString fRealName
Effective real file name (not original url)
Definition: TFile.h:85
Double_t fSumBuffer
Sum of buffer sizes of objects written so far.
Definition: TFile.h:68
@ kBinaryFile
Definition: TFile.h:181
Int_t fNProcessIDs
Number of TProcessID written to this file.
Definition: TFile.h:83
Int_t fWritten
Number of objects written so far.
Definition: TFile.h:82
TKeySQL represents meta-inforamtion about object, which was written to SQL database.
Definition: TKeySQL.h:19
Bool_t IsKeyModified(const char *keyname, const char *keytitle, const char *keydatime, Int_t cycle, const char *classname)
Compares keydata with provided and return kTRUE if key was modified Used in TFile::StreamKeysForDirec...
Definition: TKeySQL.cxx:108
Long64_t GetDBKeyId() const
Definition: TKeySQL.h:45
Long64_t GetDBDirId() const
return sql id of parent directory
Definition: TKeySQL.cxx:163
Long64_t GetDBObjId() const
Definition: TKeySQL.h:46
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual const char * GetClassName() const
Definition: TKey.h:71
virtual const char * GetTitle() const
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition: TKey.cxx:1501
const TDatime & GetDatime() const
Definition: TKey.h:77
Short_t GetCycle() const
Return cycle number associated to this key.
Definition: TKey.cxx:564
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
void Add(TObject *obj)
Definition: TObjArray.h:73
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
void MakeZombie()
Definition: TObject.h:49
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
virtual void Clear(Option_t *option="")
delete the TObjArray pointing to referenced objects this function is called by TFile::Close("R")
Definition: TProcessID.cxx:216
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:303
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0.
Definition: TProcessID.cxx:236
const char * GetSQLName() const
Definition: TSQLClassInfo.h:29
const char * GetSQLType() const
Definition: TSQLClassInfo.h:30
virtual const char * GetName() const
Returns name of object.
Definition: TSQLClassInfo.h:28
Contains information about tables specific to one class and version.
Definition: TSQLClassInfo.h:42
Bool_t IsClassTableExist() const
Definition: TSQLClassInfo.h:63
void SetRawTableName(const char *name)
Definition: TSQLClassInfo.h:54
void SetRawExist(Bool_t on)
Definition: TSQLClassInfo.h:61
void SetClassTableName(const char *name)
Definition: TSQLClassInfo.h:53
Int_t GetClassVersion() const
Definition: TSQLClassInfo.h:51
Long64_t GetClassId() const
Definition: TSQLClassInfo.h:48
const char * GetClassTableName() const
Definition: TSQLClassInfo.h:56
const char * GetRawTableName() const
Definition: TSQLClassInfo.h:57
virtual const char * GetName() const
Returns name of object.
Definition: TSQLClassInfo.h:50
void SetColumns(TObjArray *columns)
assigns new list of columns
Bool_t IsRawTableExist() const
Definition: TSQLClassInfo.h:64
Access an SQL db via the TFile interface.
Definition: TSQLFile.h:30
Bool_t CreateClassTable(TSQLClassInfo *sqlinfo, TObjArray *colinfos)
Create normal class table if required.
Definition: TSQLFile.cxx:2072
TString MakeSelectQuery(TClass *cl)
Produce SELECT statement which can be used to get all data of class cl in one SELECT statement.
Definition: TSQLFile.cxx:1225
const char * SQLIdentifierQuote() const
Definition: TSQLFile.h:136
Long64_t VerifyObjectTable()
Checks that objects table is exists If not, table will be created Returns maximum value for existing ...
Definition: TSQLFile.cxx:2318
@ kLockBusy
Definition: TSQLFile.h:41
@ kLockFree
Definition: TSQLFile.h:41
TSQLResult * GetNormalClassData(Long64_t objid, TSQLClassInfo *sqlinfo)
Method return request result for specified objid from normal classtable.
Definition: TSQLFile.cxx:2448
TObject * ReadSpecialObject(Long64_t keyid, TObject *obj=0)
Read data of special kind of objects.
Definition: TSQLFile.cxx:861
TSQLFile()
default TSQLFile constructor
Definition: TSQLFile.cxx:274
Bool_t WriteSpecialObject(Long64_t keyid, TObject *obj, const char *name, const char *title)
write special kind of object like streamer infos or file itself keys for that objects should exist in...
Definition: TSQLFile.cxx:839
void StartLogFile(const char *fname)
start logging of all SQL statements in specified file
Definition: TSQLFile.cxx:451
Bool_t fUseSuffixes
! use suffixes in column names like fValue:Int_t or fObject:pointer
Definition: TSQLFile.h:150
void AddIdEntry(Long64_t tableid, Int_t subid, Int_t type, const char *name, const char *sqlname, const char *info)
Add entry into IdsTable, where all tables names and columns names are listed.
Definition: TSQLFile.cxx:2031
Bool_t ReadConfigurations()
read table configurations as special table
Definition: TSQLFile.cxx:1064
virtual void WriteStreamerInfo()
Store all TVirtualStreamerInfo, used in file, in sql database.
Definition: TSQLFile.cxx:800
Int_t IsLongStringCode(Long64_t objid, const char *value)
Checks if this is long string code returns 0, if not or string id.
Definition: TSQLFile.cxx:2238
void CreateBasicTables()
Creates initial tables in database This is table with configurations and table with keys Function cal...
Definition: TSQLFile.cxx:1126
Int_t GetUseTransactions() const
Definition: TSQLFile.h:194
TSQLClassInfo * FindSQLClassInfo(const char *clname, Int_t version)
Return (if exists) TSQLClassInfo for specified class name and version.
Definition: TSQLFile.cxx:1785
const char * SQLDatetimeType() const
Definition: TSQLFile.h:135
void ReadSQLClassInfos()
Read all class infos from IdsTable.
Definition: TSQLFile.cxx:1924
@ kIndexesNone
Definition: TSQLFile.h:179
@ kIndexesBasic
Definition: TSQLFile.h:179
@ kIndexesClass
Definition: TSQLFile.h:179
Bool_t Commit()
Commit transaction, started by StartTransaction() call.
Definition: TSQLFile.cxx:583
void IncrementModifyCounter()
Update value of modify counter in config table Modify counter used to indicate that something was cha...
Definition: TSQLFile.cxx:1198
Int_t fArrayLimit
! limit for array size. when array bigger, its content converted to raw format
Definition: TSQLFile.h:152
friend class TKeySQL
Definition: TSQLFile.h:33
void SetLocking(Int_t mode)
Set locking mode for current database.
Definition: TSQLFile.cxx:1344
@ kTransactionsUser
Definition: TSQLFile.h:177
@ kTransactionsAuto
Definition: TSQLFile.h:177
Bool_t SQLRollback()
Rollback all SQL operations, done after start transaction.
Definition: TSQLFile.cxx:1600
TObjArray * SQLObjectsInfo(Long64_t keyid)
Produce array of TSQLObjectInfo objects for all objects, belong to that key Array should be deleted b...
Definition: TSQLFile.cxx:2384
Bool_t GetUseSuffixes() const
Definition: TSQLFile.h:186
Bool_t SQLCanStatement()
Test if DB support statement and number of open statements is not exceeded.
Definition: TSQLFile.cxx:1435
Bool_t CreateRawTable(TSQLClassInfo *sqlinfo)
Create the raw table.
Definition: TSQLFile.cxx:2154
Long64_t StoreObjectInTables(Long64_t keyid, const void *obj, const TClass *cl)
Store object in database. Return stored object id or -1 if error.
Definition: TSQLFile.cxx:2524
void InitSqlDatabase(Bool_t create)
initialize sql database and correspondent structures identical to TFile::Init() function
Definition: TSQLFile.cxx:1008
const char * SQLStrIdColumn() const
Definition: TSQLFile.h:141
Bool_t SQLObjectInfo(Long64_t objid, TString &clname, Version_t &version)
Read from objects table data for specified objectid.
Definition: TSQLFile.cxx:2357
Int_t fQuerisCounter
! how many query was applied
Definition: TSQLFile.h:159
const char * SQLValueQuote() const
Definition: TSQLFile.h:143
const char * SQLBigTextType() const
Definition: TSQLFile.h:134
Int_t GetLocking()
Return current locking mode for that file.
Definition: TSQLFile.cxx:1358
Bool_t HasTable(const char *name)
Test if table name exists.
Definition: TSQLFile.cxx:1896
TKeySQL * FindSQLKey(TDirectory *dir, Long64_t keyid)
Search for TKeySQL object with specified keyid.
Definition: TSQLFile.cxx:1682
const char * SQLDefaultTableType() const
Definition: TSQLFile.h:144
Bool_t Rollback()
Rollback all operations, done after StartTransaction() call.
Definition: TSQLFile.cxx:597
Bool_t IsWriteAccess()
Checkis, if lock is free in configuration tables.
Definition: TSQLFile.cxx:1336
void operator=(const TSQLFile &)
make private to exclude copy operator
Definition: TSQLFile.cxx:713
Bool_t IsMySQL() const
checks, if MySQL database
Definition: TSQLFile.cxx:471
void SQLDeleteAllTables()
Delete all tables in database.
Definition: TSQLFile.cxx:1560
Bool_t IsOracle() const
checks, if Oracle database
Definition: TSQLFile.cxx:481
Int_t StreamKeysForDirectory(TDirectory *dir, Bool_t doupdate, Long64_t specialkeyid=-1, TKeySQL **specialkey=0)
read keys for specified directory (when update == kFALSE) or update value for modified keys when upda...
Definition: TSQLFile.cxx:930
virtual Long64_t DirCreateEntry(TDirectory *)
Create entry for directory in database.
Definition: TSQLFile.cxx:2595
void SetTablesType(const char *table_type)
Defines tables type, which is used in CREATE TABLE statements Now is only used for MySQL database,...
Definition: TSQLFile.cxx:532
const char * SQLKeyIdColumn() const
Definition: TSQLFile.h:138
Bool_t WriteKeyData(TKeySQL *key)
Add entry into keys table.
Definition: TSQLFile.cxx:1703
void SetUseTransactions(Int_t mode=kTransactionsAuto)
Defines usage of transactions statements for writing objects data to database.
Definition: TSQLFile.cxx:552
Int_t fStmtCounter
! count numbers of active statements
Definition: TSQLFile.h:169
Bool_t fCanChangeConfig
! variable indicates can be basic configuration changed or not
Definition: TSQLFile.h:153
TString CodeLongString(Long64_t objid, Int_t strid)
Produces id which will be placed in column instead of string itself.
Definition: TSQLFile.cxx:2227
const char * SQLObjectIdColumn() const
Definition: TSQLFile.h:139
virtual ~TSQLFile()
destructor of TSQLFile object
Definition: TSQLFile.cxx:693
const char ** fOtherTypes
! pointer on list of other SQL types like TEXT or blob
Definition: TSQLFile.h:162
Bool_t fIdsTableExists
! indicate if IdsTable exists
Definition: TSQLFile.h:168
TSQLStatement * GetBlobClassDataStmt(Long64_t objid, TSQLClassInfo *sqlinfo)
Method return request results for specified objid from streamer classtable Data returned in form of s...
Definition: TSQLFile.cxx:2493
TSQLResult * GetBlobClassData(Long64_t objid, TSQLClassInfo *sqlinfo)
Method return request results for specified objid from streamer classtable.
Definition: TSQLFile.cxx:2477
virtual Int_t DirReadKeys(TDirectory *)
Read directory list of keys from database.
Definition: TSQLFile.cxx:2610
void DeleteKeyFromDB(Long64_t keyid)
Remove key with specified id from keys table also removes all objects data, related to this table.
Definition: TSQLFile.cxx:1623
Bool_t SQLTestTable(const char *tablename)
Test, if table of specified name exists.
Definition: TSQLFile.cxx:1503
const char * SQLIntType() const
return SQL integer type
Definition: TSQLFile.cxx:2587
TSQLStatement * SQLStatement(const char *cmd, Int_t bufsize=1000)
Produces SQL statement for currently conected DB server.
Definition: TSQLFile.cxx:1449
void SQLDeleteStatement(TSQLStatement *stmt)
delete statement and decrease counter
Definition: TSQLFile.cxx:1469
virtual void DirWriteHeader(TDirectory *)
Update dir header in the file.
Definition: TSQLFile.cxx:2632
TSQLResult * SQLQuery(const char *cmd, Int_t flag=0, Bool_t *res=0)
Submits query to SQL server.
Definition: TSQLFile.cxx:1399
TList * fSQLClassInfos
! list of SQL class infos
Definition: TSQLFile.h:148
std::ofstream * fLogFile
! log file with SQL statements
Definition: TSQLFile.h:166
Long64_t DefineNextKeyId()
Returns next possible key identifier.
Definition: TSQLFile.cxx:1769
TSQLResult * GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo *sqlinfo)
Return data for several objects from the range from normal class table.
Definition: TSQLFile.cxx:2462
virtual TKey * CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t bufsize)
create SQL key, which will store object in data base
Definition: TSQLFile.cxx:776
Int_t GetUseIndexes() const
Definition: TSQLFile.h:196
void SaveToDatabase()
save data which is not yet in Database Typically this is streamerinfos structures or
Definition: TSQLFile.cxx:916
virtual Int_t ReOpen(Option_t *mode)
Reopen a file with a different access mode, like from READ to See TFile::Open() for details.
Definition: TSQLFile.cxx:729
Bool_t SQLApplyCommands(TObjArray *cmds)
supplies set of commands to server Commands is stored as array of TObjString
Definition: TSQLFile.cxx:1483
const char ** fBasicTypes
! pointer on list of basic types specific for currently connected SQL server
Definition: TSQLFile.h:161
Bool_t IsReadAccess()
dummy, in future should check about read access to database
Definition: TSQLFile.cxx:1382
InfoListRet GetStreamerInfoListImpl(bool lookupSICache)
Read back streamer infos from database List of streamer infos is always stored with key:id 0,...
Definition: TSQLFile.cxx:892
Int_t SQLMaxIdentifierLength()
returns maximum allowed length of identifiers
Definition: TSQLFile.cxx:1608
Bool_t GetLongString(Long64_t objid, Int_t strid, TString &value)
Returns value of string, extracted from special table, where long strings are stored.
Definition: TSQLFile.cxx:2287
Bool_t ProduceClassSelectQuery(TVirtualStreamerInfo *info, TSQLClassInfo *sqlinfo, TString &columns, TString &tables, Int_t &tablecnt)
used by MakeClassSelectQuery method to add columns from table of class, specified by TVirtualStreamer...
Definition: TSQLFile.cxx:1247
Bool_t SQLCommit()
Commit SQL transaction.
Definition: TSQLFile.cxx:1592
const char * SQLRawIdColumn() const
Definition: TSQLFile.h:140
Bool_t UpdateKeyData(TKeySQL *key)
Updates (overwrites) key data in KeysTable.
Definition: TSQLFile.cxx:1734
Int_t fUseIndexes
! use indexes for tables: 0 - off, 1 - only for basic tables, 2 + normal class tables,...
Definition: TSQLFile.h:156
const char * GetDataBaseName() const
Return name of data base on the host For Oracle always return 0.
Definition: TSQLFile.cxx:631
void SetUseSuffixes(Bool_t on=kTRUE)
enable/disable uasge of suffixes in columns names can be changed before first object is saved into fi...
Definition: TSQLFile.cxx:502
Int_t fUseTransactions
! use transaction statements for writing data into the tables
Definition: TSQLFile.h:155
TString DefineTableName(const char *clname, Int_t version, Bool_t rawtable)
Proposes table name for class.
Definition: TSQLFile.cxx:1847
Bool_t IsTablesExists()
Checks if main keys table is existing.
Definition: TSQLFile.cxx:1328
void StopLogFile()
close logging file
Definition: TSQLFile.cxx:460
void SetArrayLimit(Int_t limit=20)
Defines maximum number of columns for array representation If array size bigger than limit,...
Definition: TSQLFile.cxx:518
Long64_t SQLMaximumValue(const char *tablename, const char *columnname)
Returns maximum value, found in specified columnname of table tablename Column type should be numeric...
Definition: TSQLFile.cxx:1523
TSQLServer * fSQL
! interface to SQL database
Definition: TSQLFile.h:146
TString fTablesType
! type, used in CREATE TABLE statements
Definition: TSQLFile.h:154
virtual void WriteHeader()
Write file info like configurations, title, UUID and other.
Definition: TSQLFile.cxx:792
TSQLClassInfo * RequestSQLClassInfo(const char *clname, Int_t version)
Search in database tables for specified class and return TSQLClassInfo object.
Definition: TSQLFile.cxx:1812
Bool_t IsODBC() const
checks, if ODBC driver used for database connection
Definition: TSQLFile.cxx:491
Int_t fModifyCounter
! indicates how many changes was done with database tables
Definition: TSQLFile.h:158
virtual Bool_t IsOpen() const
return kTRUE if file is opened and can be accessed
Definition: TSQLFile.cxx:720
const char * SQLDirIdColumn() const
Definition: TSQLFile.h:137
Int_t fSQLIOversion
! version of SQL I/O which is stored in configurations
Definition: TSQLFile.h:151
virtual void DirWriteKeys(TDirectory *)
Write directory keys list to database.
Definition: TSQLFile.cxx:2624
Bool_t StartTransaction()
Start user transaction.
Definition: TSQLFile.cxx:569
const char * SQLSmallTextType() const
Definition: TSQLFile.h:132
void SetUseIndexes(Int_t use_type=kIndexesBasic)
Specify usage of indexes for data tables.
Definition: TSQLFile.cxx:619
const char * SQLCompatibleType(Int_t typ) const
Returns sql type name which is most closer to ROOT basic type.
Definition: TSQLFile.cxx:2579
Bool_t VerifyLongStringTable()
Checks that table for big strings is exists If not, will be created.
Definition: TSQLFile.cxx:2200
Bool_t SQLStartTransaction()
Start SQL transaction.
Definition: TSQLFile.cxx:1584
virtual void Close(Option_t *option="")
Close a SQL file For more comments see TFile::Close() function.
Definition: TSQLFile.cxx:645
Info (classname, version) about object in database.
virtual TSQLRow * Next()=0
virtual const char * GetField(Int_t field)=0
virtual TList * GetTablesList(const char *wild=0)
Return list of user tables Parameter wild specifies wildcard for table names.
Definition: TSQLServer.cxx:182
virtual Bool_t Commit()
submit "COMMIT" query to database return kTRUE, if successful
Definition: TSQLServer.cxx:150
virtual Bool_t HasStatement() const
Definition: TSQLServer.h:81
virtual Int_t GetMaxIdentifierLength()
Definition: TSQLServer.h:89
virtual Bool_t HasTable(const char *tablename)
Tests if table of that name exists in database Return kTRUE, if table exists.
Definition: TSQLServer.cxx:208
virtual Bool_t Exec(const char *sql)
Execute sql query.
Definition: TSQLServer.cxx:85
virtual Bool_t Rollback()
submit "ROLLBACK" query to database return kTRUE, if successful
Definition: TSQLServer.cxx:159
virtual Bool_t StartTransaction()
submit "START TRANSACTION" query to database return kTRUE, if successful
Definition: TSQLServer.cxx:141
virtual TSQLResult * Query(const char *sql)=0
static TSQLServer * Connect(const char *db, const char *uid, const char *pw)
The db should be of the form: <dbms>://<host>[:<port>][/<database>], e.g.
Definition: TSQLServer.cxx:61
virtual TSQLStatement * Statement(const char *, Int_t=100)
Definition: TSQLServer.h:79
virtual const char * GetString(Int_t)
Definition: TSQLStatement.h:85
virtual Bool_t NextResultRow()=0
virtual Int_t GetInt(Int_t)
Definition: TSQLStatement.h:79
virtual Long64_t GetLong64(Int_t)
Definition: TSQLStatement.h:82
virtual Bool_t Process()=0
virtual Bool_t StoreResult()=0
This is hierarchical structure, which is created when data is written by TBufferSQL2.
Definition: TSQLStructure.h:94
static void AddStrBrackets(TString &s, const char *quote)
adds quotes around string value and replaces some special symbols
static Int_t DefineElementColumnType(TStreamerElement *elem, TSQLFile *f)
defines which kind of column can be assigned for this element Possible cases kColSimple - basic data ...
static TString DefineElementColumnName(TStreamerElement *elem, TSQLFile *f, Int_t indx=0)
returns name of the column in class table for that element
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetArrayLength() const
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1896
const char * Data() const
Definition: TString.h:364
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1070
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1113
TString & Append(const char *cs)
Definition: TString.h:559
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition: TUUID.h:42
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition: TUUID.cxx:560
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
virtual Int_t GetNumber() const =0
virtual TClass * GetClass() const =0
const Int_t n
Definition: legend1.C:16
static constexpr double s
Definition: first.py:1
const char * cfg_UseIndexes
const char * KT_Name
const char * StringsTable
const char * KT_Title
const Int_t Ids_RootDir
const Int_t Ids_TSQLFile
const char * ObjectsTableIndex
const char * KT_Cycle
const char * KeysTableIndex
const char * StrSuffix
const char * BT_Value
const char * OT_Version
const char * KeysTable
Long64_t atol64(const char *value)
const char * cfg_TablesType
const char * IdsTable
const char * False
const char * CT_Field
const char * CT_Value
const char * KT_Datetime
const Int_t Ids_FirstKey
const char * ST_Value
const Int_t Ids_StreamerInfos
const char * cfg_ArrayLimit
const char * IT_SubID
const char * IT_SQLName
const char * TObjectProcessId
const char * OT_Class
const char * ConfigTable
const char * cfg_UseTransactions
const char * BT_Field
const char * cfg_LockingMode
const char * cfg_UseSufixes
const char * IT_Type
const char * IT_TableID
const char * TObjectBits
const char * IT_Info
const char * True
const char * ObjectsTable
const char * KT_Class
const char * cfg_ModifyCounter
const char * cfg_Version
const char * TObjectUniqueId
const char * LongStrPrefix
const char * IT_FullName
const char * cnt
Definition: TXMLSetup.cxx:74
@ kUseGeneralPurpose
Use the recommended general-purpose setting; moderate read / write speed and compression ratio.
Definition: Compression.h:53
Simple struct of the return value of GetStreamerInfoListImpl.
Definition: TFile.h:138