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