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