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