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