Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TSQLStructure.cxx
Go to the documentation of this file.
1// @(#)root/sql:$Id$
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 TSQLStructure
14\ingroup IO
15This is hierarchical structure, which is created when data is written
16by TBufferSQL2. It contains data all structural information such:
17version of written class, data member types of that class, value for
18each data member and so on.
19Such structure in some sense similar to XML node and subnodes structure
20Once it created, it converted to SQL statements, which are submitted
21to database server.
22*/
23
24#include "TSQLStructure.h"
25
26#include "TMap.h"
27#include "TClass.h"
28#include "TStreamerInfo.h"
29#include "TStreamerElement.h"
30#include "TObjString.h"
31
32#include "TSQLFile.h"
33#include "TSQLClassInfo.h"
34#include "TSQLObjectData.h"
35#include "TBufferSQL2.h"
36
37#include "TSQLStatement.h"
38#include "TSQLServer.h"
39#include "TDataType.h"
40
41#include <iostream>
42
43namespace sqlio {
44const Int_t Ids_NullPtr = 0; // used to identify NULL pointer in tables
45const Int_t Ids_RootDir = 0; // dir:id, used for keys stored in root directory.
46const Int_t Ids_TSQLFile = 0; // keyid for TSQLFile entry in keys list
47const Int_t Ids_StreamerInfos = 1; // keyid used to store StreamerInfos in ROOT directory
48const Int_t Ids_FirstKey = 10; // first key id, which is used in KeysTable (beside streamer info or something else)
49const Int_t Ids_FirstObject = 1; // first object id, allowed in object tables
50
51const char *ObjectRef = "ObjectRef";
52const char *ObjectRef_Arr = "ObjectRefArr";
53const char *ObjectPtr = "ObjectPtr";
54const char *ObjectInst = "ObjectInst";
55const char *Version = "Version";
56const char *TObjectUniqueId = "UniqueId";
57const char *TObjectBits = "Bits";
58const char *TObjectProcessId = "ProcessId";
59const char *TStringValue = "StringValue";
60const char *IndexSepar = "..";
61const char *RawSuffix = ":rawdata";
62const char *ParentSuffix = ":parent";
63const char *ObjectSuffix = ":object";
64const char *PointerSuffix = ":pointer";
65const char *StrSuffix = ":str";
66const char *LongStrPrefix = "#~#";
67
68const char *Array = "Array";
69const char *Bool = "Bool_t";
70const char *Char = "Char_t";
71const char *Short = "Short_t";
72const char *Int = "Int_t";
73const char *Long = "Long_t";
74const char *Long64 = "Long64_t";
75const char *Float = "Float_t";
76const char *Double = "Double_t";
77const char *UChar = "UChar_t";
78const char *UShort = "UShort_t";
79const char *UInt = "UInt_t";
80const char *ULong = "ULong_t";
81const char *ULong64 = "ULong64_t";
82const char *CharStar = "CharStar";
83const char *True = "1";
84const char *False = "0";
85
86// standard tables names
87const char *KeysTable = "KeysTable";
88const char *KeysTableIndex = "KeysTableIndex";
89const char *ObjectsTable = "ObjectsTable";
90const char *ObjectsTableIndex = "ObjectsTableIndex";
91const char *IdsTable = "IdsTable";
92const char *IdsTableIndex = "IdsTableIndex";
93const char *StringsTable = "StringsTable";
94const char *ConfigTable = "Configurations";
95
96// columns in Keys table
97const char *KT_Name = "Name";
98const char *KT_Title = "Title";
99const char *KT_Datetime = "Datime";
100const char *KT_Cycle = "Cycle";
101const char *KT_Class = "Class";
102
103const char *DT_Create = "CreateDatime";
104const char *DT_Modified = "ModifiedDatime";
105const char *DT_UUID = "UUID";
106
107// columns in Objects table
108const char *OT_Class = "Class";
109const char *OT_Version = "Version";
110
111// columns in Identifiers Table
112const char *IT_TableID = "TableId";
113const char *IT_SubID = "SubId";
114const char *IT_Type = "Type";
115const char *IT_FullName = "FullName";
116const char *IT_SQLName = "SQLName";
117const char *IT_Info = "Info";
118
119// colummns in _streamer_ tables
120const char *BT_Field = "Field";
121const char *BT_Value = "Value";
122
123// colummns in string table
124const char *ST_Value = "LongStringValue";
125
126// columns in config table
127const char *CT_Field = "Field";
128const char *CT_Value = "Value";
129
130// values in config table
131const char *cfg_Version = "SQL_IO_version";
132const char *cfg_UseSufixes = "UseNameSuffix";
133const char *cfg_ArrayLimit = "ArraySizeLimit";
134const char *cfg_TablesType = "TablesType";
135const char *cfg_UseTransactions = "UseTransactions";
136const char *cfg_UseIndexes = "UseIndexes";
137const char *cfg_LockingMode = "LockingMode";
138const char *cfg_ModifyCounter = "ModifyCounter";
139};
140
141//________________________________________________________________________
142
144{
145 if (!value || (*value == 0))
146 return 0;
147 return TString(value).Atoll();
148}
149
150/**
151\class TSQLColumnData
152\ingroup IO
153*/
154
156
157////////////////////////////////////////////////////////////////////////////////
158/// normal constructor of TSQLColumnData class
159/// specifies name, type and value for one column
160
161TSQLColumnData::TSQLColumnData(const char *name, const char *sqltype, const char *value, Bool_t numeric)
162 : TObject(), fName(name), fType(sqltype), fValue(value), fNumeric(numeric)
163{
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// constructs TSQLColumnData object for integer column
168
170 : TObject(), fName(name), fType("INT"), fValue(), fNumeric(kTRUE)
171{
172 fValue.Form("%lld", value);
173}
174
176
177////////////////////////////////////////////////////////////////////////////////
178/// normal constructor
179
181 : TObject(), fFile(f), fInfo(info)
182{
183 if (info && !info->IsClassTableExist())
184 fColInfos = new TObjArray;
185}
186
187////////////////////////////////////////////////////////////////////////////////
188/// destructor
189
191{
193 if (fColInfos) {
194 fColInfos->Delete();
195 delete fColInfos;
196 }
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Add INT column to list of columns
201
203{
204 TObjString *v = new TObjString(Form("%lld", value));
205 v->SetBit(BIT(20), kTRUE);
206 fColumns.Add(v);
207
208 // TSQLColumnData* col = new TSQLColumnData(name, value);
209 // fColumns.Add(col);
210
211 if (fColInfos)
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Add normal column to list of columns
217
218void TSQLTableData::AddColumn(const char *name, const char *sqltype, const char *value, Bool_t numeric)
219{
221 v->SetBit(BIT(20), numeric);
222 fColumns.Add(v);
223
224 // TSQLColumnData* col = new TSQLColumnData(name, sqltype, value, numeric);
225 // fColumns.Add(col);
226
227 if (fColInfos)
229}
230
231////////////////////////////////////////////////////////////////////////////////
232/// produce suitable name for column, taking into account length limitation
233
235{
237
238 Int_t len = strlen(fullname);
239
240 if ((len <= maxlen) && !HasSQLName(fullname))
241 return TString(fullname);
242
243 Int_t cnt = -1;
244 TString res, scnt;
245
246 do {
247
248 scnt.Form("%d", cnt);
249 Int_t numlen = cnt < 0 ? 0 : scnt.Length();
250
251 res = fullname;
252
253 if (len + numlen > maxlen)
254 res.Resize(maxlen - numlen);
255
256 if (cnt >= 0)
257 res += scnt;
258
259 if (!HasSQLName(res.Data()))
260 return res;
261
262 cnt++;
263
264 } while (cnt < 10000);
265
266 Error("DefineSQLName", "Cannot find reasonable column name for field %s", fullname);
267
268 return TString(fullname);
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// checks if columns list already has that sql name
273
275{
276 TIter next(fColInfos);
277
278 TSQLClassColumnInfo *col = nullptr;
279
280 while ((col = (TSQLClassColumnInfo *)next()) != nullptr) {
281 const char *colname = col->GetSQLName();
282 if (strcmp(colname, sqlname) == 0)
283 return kTRUE;
284 }
285
286 return kFALSE;
287}
288
289////////////////////////////////////////////////////////////////////////////////
290/// returns number of columns in provided set
291
293{
294 return fColumns.GetLast() + 1;
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// return column value
299
301{
302 return fColumns[n]->GetName();
303}
304
305////////////////////////////////////////////////////////////////////////////////
306/// identifies if column has numeric value
307
309{
310 return fColumns[n]->TestBit(BIT(20));
311}
312
313////////////////////////////////////////////////////////////////////////////////
314/// take ownership over colinfos
315
317{
318 TObjArray *res = fColInfos;
319 fColInfos = nullptr;
320 return res;
321}
322
323//________________________________________________________________________
324
326
327////////////////////////////////////////////////////////////////////////////////
328/// destructor
329
331{
332 fChilds.Delete();
333 if (GetType() == kSqlObjectData) {
335 delete objdata;
336 } else if (GetType() == kSqlCustomElement) {
338 delete elem;
339 }
340}
341
342////////////////////////////////////////////////////////////////////////////////
343/// number of child structures
344
346{
347 return fChilds.GetLast() + 1;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// return child structure of index n
352
354{
355 return (n < 0) || (n > fChilds.GetLast()) ? nullptr : (TSQLStructure *)fChilds[n];
356}
357
358////////////////////////////////////////////////////////////////////////////////
359/// set structure type as kSqlObject
360
362{
364 fValue.Form("%lld", refid);
365 fPointer = cl;
366}
367
368////////////////////////////////////////////////////////////////////////////////
369/// set structure type as kSqlPointer
370
372{
374 fValue.Form("%lld", ptrid);
375}
376
377////////////////////////////////////////////////////////////////////////////////
378/// set structure type as kSqlVersion
379
380void TSQLStructure::SetVersion(const TClass *cl, Int_t version)
381{
383 fPointer = cl;
384 if (version < 0)
385 version = cl->GetClassVersion();
386 fValue.Form("%d", version);
387}
388
389////////////////////////////////////////////////////////////////////////////////
390/// set structure type as kSqlClassStreamer
391
393{
395 fPointer = cl;
396}
397
398////////////////////////////////////////////////////////////////////////////////
399/// set structure type as kSqlStreamerInfo
400
402{
404 fPointer = info;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408/// set structure type as kSqlElement
409
411{
413 fPointer = elem;
414 fArrayIndex = number;
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// set structure type as kSqlCustomClass
419
421{
423 fPointer = (void *)cl;
424 fArrayIndex = version;
425}
426
427////////////////////////////////////////////////////////////////////////////////
428/// set structure type as kSqlCustomElement
429
431{
433 fPointer = elem;
434}
435
436////////////////////////////////////////////////////////////////////////////////
437/// set structure type as kSqlValue
438
439void TSQLStructure::SetValue(const char *value, const char *tname)
440{
442 fValue = value;
443 fPointer = tname;
444}
445
446////////////////////////////////////////////////////////////////////////////////
447/// change value of this structure
448/// used as "workaround" to keep object id in kSqlElement node
449
451{
452 fValue = value;
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// set array index for this structure
457
459{
460 fArrayIndex = indx;
461 fRepeatCnt = cnt;
462}
463
464////////////////////////////////////////////////////////////////////////////////
465/// set array index for last child element
466/// if (cnt<=1) return;
467
469{
471 if (last && (last->GetType() == kSqlValue))
472 last->SetArrayIndex(index, cnt);
473}
474
475////////////////////////////////////////////////////////////////////////////////
476/// Set structure as array element
477
479{
481 if (sz >= 0)
482 fValue.Form("%d", sz);
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// return object class if type kSqlObject
487
489{
490 return (fType == kSqlObject) ? (TClass *)fPointer : nullptr;
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// return class for version tag if type is kSqlVersion
495
497{
498 return (fType == kSqlVersion) ? (TClass *)fPointer : nullptr;
499}
500
501////////////////////////////////////////////////////////////////////////////////
502/// return TStreamerInfo* if type is kSqlStreamerInfo
503
505{
506 return (fType == kSqlStreamerInfo) ? (TStreamerInfo *)fPointer : nullptr;
507}
508
509////////////////////////////////////////////////////////////////////////////////
510/// return TStremerElement* if type is kSqlElement
511
513{
514 return (fType == kSqlElement) || (fType == kSqlCustomElement) ? (TStreamerElement *)fPointer : nullptr;
515}
516
517////////////////////////////////////////////////////////////////////////////////
518/// returns number of TStremerElement in TStreamerInfo
519
521{
522 return (fType == kSqlElement) ? fArrayIndex : 0;
523}
524
525////////////////////////////////////////////////////////////////////////////////
526/// return value type if structure is kSqlValue
527
529{
530 return (fType == kSqlValue) ? (const char *)fPointer : nullptr;
531}
532
533////////////////////////////////////////////////////////////////////////////////
534/// return element custom class if structures is kSqlCustomClass
535
537{
538 return (fType == kSqlCustomClass) ? (TClass *)fPointer : nullptr;
539}
540
541////////////////////////////////////////////////////////////////////////////////
542/// return custom class version if structures is kSqlCustomClass
543
545{
546 return (fType == kSqlCustomClass) ? fArrayIndex : 0;
547}
548
549////////////////////////////////////////////////////////////////////////////////
550/// provides class info if structure kSqlStreamerInfo or kSqlCustomClass
551
553{
554 if (GetType() == kSqlStreamerInfo) {
556 if (!info)
557 return kFALSE;
558 cl = info->GetClass();
559 version = info->GetClassVersion();
560 } else if (GetType() == kSqlCustomClass) {
561 cl = GetCustomClass();
562 version = GetCustomClassVersion();
563 } else
564 return kFALSE;
565 return kTRUE;
566}
567
568////////////////////////////////////////////////////////////////////////////////
569/// returns value
570/// for different structure kinds has different sense
571/// For kSqlVersion it version, for kSqlReference it is object id and so on
572
573const char *TSQLStructure::GetValue() const
574{
575 return fValue.Data();
576}
577
578////////////////////////////////////////////////////////////////////////////////
579/// Add child structure
580
582{
583 if (child) {
584 child->SetParent(this);
586 }
587}
588
589////////////////////////////////////////////////////////////////////////////////
590/// add child as version
591
592void TSQLStructure::AddVersion(const TClass *cl, Int_t version)
593{
594 TSQLStructure *ver = new TSQLStructure;
595 ver->SetVersion(cl, version);
596 Add(ver);
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Add child structure as value
601
602void TSQLStructure::AddValue(const char *value, const char *tname)
603{
605 child->SetValue(value, tname);
606 Add(child);
607}
608
609////////////////////////////////////////////////////////////////////////////////
610/// defines current object id, to which this structure belong
611/// make life complicated, because some objects do not get id
612/// automatically in TBufferSQL, but afterwards
613
615{
616 TSQLStructure *curr = this;
617 while (curr) {
618 if ((curr->GetType() == kSqlObject) || (curr->GetType() == kSqlPointer) ||
619 // workaround to store object id in element structure
620 (curr->GetType() == kSqlElement) || (curr->GetType() == kSqlCustomElement) ||
621 (curr->GetType() == kSqlCustomClass) || (curr->GetType() == kSqlStreamerInfo)) {
622 const char *value = curr->GetValue();
623 if (value && (strlen(value) > 0))
624 return sqlio::atol64(value);
625 }
626
627 curr = recursive ? curr->GetParent() : nullptr;
628 }
629 return -1;
630}
631
632////////////////////////////////////////////////////////////////////////////////
633/// set element to be used for object data
634
636{
638 fPointer = objdata;
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// add element with pointer to object data
643
645{
647 child->SetObjectData(objdata);
648 Add(child);
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// searches for objects data
653
655{
657 if (child && (child->GetType() == kSqlObjectData))
658 return (TSQLObjectData *)child->fPointer;
659 if (search && GetParent())
660 return GetParent()->GetObjectData(search);
661 return nullptr;
662}
663
664////////////////////////////////////////////////////////////////////////////////
665/// print content of complete structure
666
668{
669 PrintLevel(0);
670}
671
672////////////////////////////////////////////////////////////////////////////////
673/// print content of current structure
674
676{
677 for (Int_t n = 0; n < level; n++)
678 std::cout << " ";
679 switch (fType) {
680 case 0: std::cout << "Undefined type"; break;
681 case kSqlObject: std::cout << "Object ref = " << fValue; break;
682 case kSqlPointer: std::cout << "Pointer ptr = " << fValue; break;
683 case kSqlVersion: {
684 const TClass *cl = (const TClass *)fPointer;
685 std::cout << "Version cl = " << cl->GetName() << " ver = " << cl->GetClassVersion();
686 break;
687 }
688 case kSqlStreamerInfo: {
689 const TStreamerInfo *info = (const TStreamerInfo *)fPointer;
690 std::cout << "Class: " << info->GetName();
691 break;
692 }
694 case kSqlElement: {
695 const TStreamerElement *elem = (const TStreamerElement *)fPointer;
696 std::cout << "Member: " << elem->GetName();
697 break;
698 }
699 case kSqlValue: {
700 std::cout << "Value: " << fValue;
701 if (fRepeatCnt > 1)
702 std::cout << " cnt:" << fRepeatCnt;
703 if (fPointer)
704 std::cout << " type = " << (const char *)fPointer;
705 break;
706 }
707 case kSqlArray: {
708 std::cout << "Array ";
709 if (fValue.Length() > 0)
710 std::cout << " sz = " << fValue;
711 break;
712 }
713 case kSqlCustomClass: {
714 TClass *cl = (TClass *)fPointer;
715 std::cout << "CustomClass: " << cl->GetName() << " ver = " << fValue;
716 break;
717 }
718 default: std::cout << "Unknown type";
719 }
720 std::cout << std::endl;
721
722 for (Int_t n = 0; n < NumChilds(); n++)
723 GetChild(n)->PrintLevel(level + 2);
724}
725
726////////////////////////////////////////////////////////////////////////////////
727/// defines if value is numeric and not requires quotes when writing
728
730{
731 switch (typ) {
732 case TStreamerInfo::kShort: return kTRUE;
733 case TStreamerInfo::kInt: return kTRUE;
734 case TStreamerInfo::kLong: return kTRUE;
735 case TStreamerInfo::kFloat: return kTRUE;
736 case TStreamerInfo::kFloat16: return kTRUE;
737 case TStreamerInfo::kCounter: return kTRUE;
738 case TStreamerInfo::kDouble: return kTRUE;
739 case TStreamerInfo::kDouble32: return kTRUE;
740 case TStreamerInfo::kUChar: return kTRUE;
741 case TStreamerInfo::kUShort: return kTRUE;
742 case TStreamerInfo::kUInt: return kTRUE;
743 case TStreamerInfo::kULong: return kTRUE;
744 case TStreamerInfo::kBits: return kTRUE;
745 case TStreamerInfo::kLong64: return kTRUE;
746 case TStreamerInfo::kULong64: return kTRUE;
747 case TStreamerInfo::kBool: return kTRUE;
748 }
749 return kFALSE;
750}
751
752////////////////////////////////////////////////////////////////////////////////
753/// provides name for basic types
754/// used as suffix for column name or field suffix in raw table
755
757{
758 switch (typ) {
761 case TStreamerInfo::kInt: return sqlio::Int;
776 }
777
778 return nullptr;
779}
780
781//___________________________________________________________
782
783// TSqlCmdsBuffer used as buffer for data, which are correspond to
784// particular class, defined by TSQLClassInfo instance
785// Support both TSQLStatement and Query modes
786
787class TSqlCmdsBuffer : public TObject {
788
789public:
790 TSqlCmdsBuffer(TSQLFile *f, TSQLClassInfo *info) : TObject(), fFile(f), fInfo(info), fBlobStmt(nullptr), fNormStmt(nullptr) {}
791
793 {
798 }
799
800 void AddValues(Bool_t isnorm, const char *values)
801 {
802 TObjString *str = new TObjString(values);
803 if (isnorm)
804 fNormCmds.Add(str);
805 else
806 fBlobCmds.Add(str);
807 }
808
815};
816
817//________________________________________________________________________
818// TSqlRegistry keeps data, used when object data transformed to sql query or
819// statements
820
821class TSqlRegistry : public TObject {
822
823public:
825 : TObject(), fFile(nullptr), fKeyId(0), fLastObjId(-1), fCmds(nullptr), fFirstObjId(0), fCurrentObjId(0), fCurrentObjClass(nullptr),
827 {
828 }
829
835
838
840
844
846
847 ~TSqlRegistry() override
848 {
853 }
854
856
857 void AddSqlCmd(const char *query)
858 {
859 // add SQL command to the list
860 if (!fCmds)
861 fCmds = new TObjArray;
862 fCmds->Add(new TObjString(query));
863 }
864
866 {
867 if (!sqlinfo)
868 return nullptr;
869 TSqlCmdsBuffer *buf = (TSqlCmdsBuffer *)fPool.GetValue(sqlinfo);
870 if (!buf) {
871 buf = new TSqlCmdsBuffer(fFile, sqlinfo);
872 fPool.Add(sqlinfo, buf);
873 }
874 return buf;
875 }
876
877 void ConvertSqlValues(TObjArray &values, const char *tablename)
878 {
879 // this function transforms array of values for one table
880 // to SQL command. For MySQL one INSERT query can
881 // contain data for more than one row
882
883 if ((values.GetLast() < 0) || !tablename)
884 return;
885
886 Bool_t canbelong = fFile->IsMySQL();
887
888 Int_t maxsize = 50000;
889 TString sqlcmd(maxsize), value, onecmd, cmdmask;
890
891 const char *quote = fFile->SQLIdentifierQuote();
892
893 TIter iter(&values);
894 TObject *cmd = nullptr;
895 while ((cmd = iter()) != nullptr) {
896
897 if (sqlcmd.Length() == 0)
898 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", quote, tablename, quote, cmd->GetName());
899 else {
900 sqlcmd += ", (";
901 sqlcmd += cmd->GetName();
902 sqlcmd += ")";
903 }
904
905 if (!canbelong || (sqlcmd.Length() > maxsize * 0.9)) {
906 AddSqlCmd(sqlcmd.Data());
907 sqlcmd = "";
908 }
909 }
910
911 if (sqlcmd.Length() > 0)
912 AddSqlCmd(sqlcmd.Data());
913 }
914
916 {
917 TSQLClassInfo *sqlinfo = nullptr;
918 TIter iter(&fPool);
919 while ((sqlinfo = (TSQLClassInfo *)iter()) != nullptr) {
920 TSqlCmdsBuffer *buf = (TSqlCmdsBuffer *)fPool.GetValue(sqlinfo);
921 if (!buf)
922 continue;
924 // ensure that raw table will be created
925 if (buf->fBlobCmds.GetLast() >= 0)
926 fFile->CreateRawTable(sqlinfo);
928 if (buf->fBlobStmt)
929 buf->fBlobStmt->Process();
930 if (buf->fNormStmt)
931 buf->fNormStmt->Process();
932 }
933
936 if (fRegStmt)
937 fRegStmt->Process();
938 }
939
940 void AddRegCmd(Long64_t objid, TClass *cl)
941 {
942 Long64_t indx = objid - fFirstObjId;
943 if (indx < 0) {
944 Error("AddRegCmd", "Something wrong with objid = %lld", objid);
945 return;
946 }
947
948 if (fFile->IsOracle() || fFile->IsODBC()) {
949 if (!fRegStmt&& fFile->SQLCanStatement()) {
950 const char *quote = fFile->SQLIdentifierQuote();
951
952 TString sqlcmd;
953 const char *pars = fFile->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
954 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", quote, sqlio::ObjectsTable, quote, pars);
955 fRegStmt = fFile->SQLStatement(sqlcmd.Data(), 1000);
956 }
957
958 if (fRegStmt) {
961 fRegStmt->SetLong64(1, objid);
964 return;
965 }
966 }
967
968 const char *valuequote = fFile->SQLValueQuote();
969 TString cmd;
970 cmd.Form("%lld, %lld, %s%s%s, %d", fKeyId, objid, valuequote, cl->GetName(), valuequote, cl->GetClassVersion());
971 fRegValues.AddAtAndExpand(new TObjString(cmd), indx);
972 }
973
974 Int_t AddLongString(const char *strvalue)
975 {
976 // add value to special string table,
977 // where large (more than 255 bytes) strings are stored
978
979 if (fLastLongStrId == 0)
981 Int_t strid = ++fLastLongStrId;
982 TString value = strvalue;
983 const char *valuequote = fFile->SQLValueQuote();
985
986 TString cmd;
987 cmd.Form("%lld, %d, %s", fCurrentObjId, strid, value.Data());
988
989 fLongStrValues.Add(new TObjString(cmd));
990
991 return strid;
992 }
993
995 {
996 TSqlCmdsBuffer *buf = GetCmdsBuffer(sqlinfo);
997 if (!buf)
998 return kFALSE;
999
1000 TSQLStatement *stmt = buf->fNormStmt;
1001 if (!stmt) {
1002 // if one cannot create statement, do it normal way
1003 if (!fFile->SQLCanStatement())
1004 return kFALSE;
1005
1006 const char *quote = fFile->SQLIdentifierQuote();
1007 TString sqlcmd;
1008 sqlcmd.Form("INSERT INTO %s%s%s VALUES (", quote, sqlinfo->GetClassTableName(), quote);
1009 for (int n = 0; n < columns->GetNumColumns(); n++) {
1010 if (n > 0)
1011 sqlcmd += ", ";
1012 if (fFile->IsOracle()) {
1013 sqlcmd += ":";
1014 sqlcmd += (n + 1);
1015 } else
1016 sqlcmd += "?";
1017 }
1018 sqlcmd += ")";
1019
1020 stmt = fFile->SQLStatement(sqlcmd.Data(), 1000);
1021 if (!stmt)
1022 return kFALSE;
1023 buf->fNormStmt = stmt;
1024 }
1025
1026 stmt->NextIteration();
1027
1028 Int_t sizelimit = fFile->SQLSmallTextTypeLimit();
1029
1030 for (Int_t ncol = 0; ncol < columns->GetNumColumns(); ncol++) {
1031 const char *value = columns->GetColumn(ncol);
1032 if (!value)
1033 value = "";
1034 stmt->SetString(ncol, value, sizelimit);
1035 }
1036
1037 return kTRUE;
1038 }
1039
1041 {
1042 // produce SQL query to insert object data into normal table
1043
1044 if (fFile->IsOracle() || fFile->IsODBC())
1045 if (InsertToNormalTableOracle(columns, sqlinfo))
1046 return;
1047
1048 const char *valuequote = fFile->SQLValueQuote();
1049
1050 TString values;
1051
1052 for (Int_t n = 0; n < columns->GetNumColumns(); n++) {
1053 if (n > 0)
1054 values += ", ";
1055
1056 if (columns->IsNumeric(n))
1057 values += columns->GetColumn(n);
1058 else {
1059 TString value = columns->GetColumn(n);
1061 values += value;
1062 }
1063 }
1064
1065 TSqlCmdsBuffer *buf = GetCmdsBuffer(sqlinfo);
1066 if (buf)
1067 buf->AddValues(kTRUE, values.Data());
1068 }
1069};
1070
1071//_____________________________________________________________________________
1072
1073// TSqlRawBuffer is used to convert raw data, which corresponds to one
1074// object and belong to single SQL tables. Supports both statements
1075// and query mode
1076
1077class TSqlRawBuffer : public TObject {
1078
1079public:
1081 : TObject(), fFile(nullptr), fInfo(nullptr), fCmdBuf(nullptr), fObjId(0), fRawId(0), fValueMask(), fValueQuote(nullptr), fMaxStrSize(255)
1082 {
1083 fFile = reg->fFile;
1084 fInfo = sqlinfo;
1085 fCmdBuf = reg->GetCmdsBuffer(sqlinfo);
1086 fObjId = reg->fCurrentObjId;
1088 fValueMask.Form("%lld, %s, %s%s%s, %s", fObjId, "%d", fValueQuote, "%s", fValueQuote, "%s");
1089 fMaxStrSize = reg->fFile->SQLSmallTextTypeLimit();
1090 }
1091
1093 {
1094 // close blob statement for Oracle
1096 if (stmt && fFile->IsOracle()) {
1097 stmt->Process();
1098 delete stmt;
1099 fCmdBuf->fBlobStmt = nullptr;
1100 }
1101 }
1102
1103 Bool_t IsAnyData() const { return fRawId > 0; }
1104
1105 void AddLine(const char *name, const char *value, const char *topname = nullptr, const char *ns = nullptr)
1106 {
1107 if (!fCmdBuf)
1108 return;
1109
1110 // when first line is created, check all problems
1111 if (fRawId == 0) {
1112 Bool_t maketmt = kFALSE;
1113 if (fFile->IsOracle() || fFile->IsODBC())
1114 maketmt = !fCmdBuf->fBlobStmt && fFile->SQLCanStatement();
1115
1116 if (maketmt) {
1117 // ensure that raw table is exists
1119
1120 const char *quote = fFile->SQLIdentifierQuote();
1121 TString sqlcmd;
1122 const char *params = fFile->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
1123 sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", quote, fInfo->GetRawTableName(), quote, params);
1124 TSQLStatement *stmt = fFile->SQLStatement(sqlcmd.Data(), 2000);
1125 fCmdBuf->fBlobStmt = stmt;
1126 }
1127 }
1128
1129 TString buf;
1130 const char *fullname = name;
1131 if (topname && ns) {
1132 buf += topname;
1133 buf += ns;
1134 buf += name;
1135 fullname = buf.Data();
1136 }
1137
1139
1140 if (stmt) {
1141 stmt->NextIteration();
1142 stmt->SetLong64(0, fObjId);
1143 stmt->SetInt(1, fRawId++);
1144 stmt->SetString(2, fullname, fMaxStrSize);
1145 // Info("AddLine","name = %s value = %s",fullname, value);
1146 stmt->SetString(3, value, fMaxStrSize);
1147 } else {
1148 TString valuebuf(value);
1150 TString cmd;
1151 cmd.Form(fValueMask.Data(), fRawId++, fullname, valuebuf.Data());
1152 fCmdBuf->AddValues(kFALSE, cmd.Data());
1153 }
1154 }
1155
1162 const char *fValueQuote;
1164};
1165
1166////////////////////////////////////////////////////////////////////////////////
1167/// define maximum reference id, used for objects
1168
1170{
1172
1173 for (Int_t n = 0; n < NumChilds(); n++) {
1175 if (zn > max)
1176 max = zn;
1177 }
1178
1179 return max;
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Convert structure to sql statements
1184/// This function is called immediately after TBufferSQL2 produces
1185/// this structure with object data
1186/// Should be only called for toplevel structure
1187
1189{
1190 if (!file || !cmds)
1191 return kFALSE;
1192
1194
1195 reg.fCmds = cmds;
1196 reg.fFile = file;
1197 reg.fKeyId = keyid;
1198 // this is id of main object to be stored
1199 reg.fFirstObjId = DefineObjectId(kFALSE);
1200 // this is maximum objectid which is now in use
1201 reg.fLastObjId = FindMaxObjectId();
1202
1203 Bool_t res = StoreObject(&reg, reg.fFirstObjId, GetObjectClass());
1204
1205 // convert values from pool to SQL commands
1206 reg.ConvertPoolValues();
1207
1208 return res;
1209}
1210
1211////////////////////////////////////////////////////////////////////////////////
1212/// perform conversion of structure to sql statements
1213/// first tries convert it to normal form
1214/// if fails, produces data for raw table
1215
1216void TSQLStructure::PerformConversion(TSqlRegistry *reg, TSqlRawBuffer *blobs, const char *topname, Bool_t useblob)
1217{
1218 TString sbuf;
1219 const char *ns = reg->fFile->SQLNameSeparator();
1220
1221 switch (fType) {
1222 case kSqlObject: {
1223
1225 break;
1226
1227 blobs->AddLine(sqlio::ObjectRef, GetValue(), topname, ns);
1228
1229 break;
1230 }
1231
1232 case kSqlPointer: {
1233 blobs->AddLine(sqlio::ObjectPtr, fValue.Data(), topname, ns);
1234 break;
1235 }
1236
1237 case kSqlVersion: {
1238 if (fPointer)
1239 topname = ((TClass *)fPointer)->GetName();
1240 else
1241 Error("PerformConversion", "version without class");
1242 blobs->AddLine(sqlio::Version, fValue.Data(), topname, ns);
1243 break;
1244 }
1245
1246 case kSqlStreamerInfo: {
1247
1249 if (!info)
1250 return;
1251
1252 if (useblob) {
1253 for (Int_t n = 0; n <= fChilds.GetLast(); n++) {
1255 child->PerformConversion(reg, blobs, info->GetName(), useblob);
1256 }
1257 } else {
1258 Long64_t objid = reg->GetNextObjId();
1259 TString sobjid;
1260 sobjid.Form("%lld", objid);
1261 if (!StoreObject(reg, objid, info->GetClass(), kTRUE))
1262 return;
1263 blobs->AddLine(sqlio::ObjectInst, sobjid.Data(), topname, ns);
1264 }
1265 break;
1266 }
1267
1268 case kSqlCustomElement:
1269 case kSqlElement: {
1270 const TStreamerElement *elem = (const TStreamerElement *)fPointer;
1271
1272 Int_t indx = 0;
1273 while (indx < NumChilds()) {
1274 TSQLStructure *child = GetChild(indx++);
1275 child->PerformConversion(reg, blobs, elem->GetName(), useblob);
1276 }
1277 break;
1278 }
1279
1280 case kSqlValue: {
1281 const char *tname = (const char *)fPointer;
1282 if (fArrayIndex >= 0) {
1283 if (fRepeatCnt > 1)
1284 sbuf.Form("%s%d%s%d%s%s%s", "[", fArrayIndex, sqlio::IndexSepar, fArrayIndex + fRepeatCnt - 1, "]", ns,
1285 tname);
1286 else
1287 sbuf.Form("%s%d%s%s%s", "[", fArrayIndex, "]", ns, tname);
1288 } else {
1289 if (tname)
1290 sbuf = tname;
1291 else
1292 sbuf = "Value";
1293 }
1294
1295 TString buf;
1296 const char *value = fValue.Data();
1297
1298 if ((tname == sqlio::CharStar) && value) {
1299 Int_t size = strlen(value);
1300 if (size > reg->fFile->SQLSmallTextTypeLimit()) {
1301 Int_t strid = reg->AddLongString(value);
1302 buf = reg->fFile->CodeLongString(reg->fCurrentObjId, strid);
1303 value = buf.Data();
1304 }
1305 }
1306
1307 blobs->AddLine(sbuf.Data(), value, (fArrayIndex >= 0) ? nullptr : topname, ns);
1308
1309 break;
1310 }
1311
1312 case kSqlArray: {
1313 if (fValue.Length() > 0)
1314 blobs->AddLine(sqlio::Array, fValue.Data(), topname, ns);
1315 for (Int_t n = 0; n <= fChilds.GetLast(); n++) {
1317 child->PerformConversion(reg, blobs, topname, useblob);
1318 }
1319 break;
1320 }
1321 }
1322}
1323
1324////////////////////////////////////////////////////////////////////////////////
1325/// convert object data to sql statements
1326/// if normal (column-wise) representation is not possible,
1327/// complete object will be converted to raw format
1328
1330{
1331 if (!cl || (objid < 0))
1332 return kFALSE;
1333
1334 if (gDebug > 1) {
1335 std::cout << "Store object " << objid << " cl = " << cl->GetName() << std::endl;
1336 if (GetStreamerInfo())
1337 std::cout << "Info = " << GetStreamerInfo()->GetName() << std::endl;
1338 else if (GetElement())
1339 std::cout << "Element = " << GetElement()->GetName() << std::endl;
1340 }
1341
1342 Long64_t oldid = reg->fCurrentObjId;
1343 TClass *oldcl = reg->fCurrentObjClass;
1344
1345 reg->fCurrentObjId = objid;
1346 reg->fCurrentObjClass = cl;
1347
1348 Bool_t normstore = kFALSE;
1349
1350 Bool_t res = kTRUE;
1351
1352 if (cl == TObject::Class())
1353 normstore = StoreTObject(reg);
1354 else if (cl == TString::Class())
1355 normstore = StoreTString(reg);
1356 else if (GetType() == kSqlStreamerInfo)
1357 // this is a case when array of objects are stored in blob and each object
1358 // has normal streamer. Then it will be stored in normal form and only one tag
1359 // will be kept to remind about
1360 normstore = StoreClassInNormalForm(reg);
1361 else
1362 normstore = StoreObjectInNormalForm(reg);
1363
1364 if (gDebug > 2)
1365 std::cout << "Store object " << objid << " of class " << cl->GetName() << " normal = " << normstore
1366 << " sqltype = " << GetType() << std::endl;
1367
1368 if (!normstore) {
1369
1370 // This is a case, when only raw table is exists
1371
1372 TSQLClassInfo *sqlinfo = reg->fFile->RequestSQLClassInfo(cl);
1373 TSqlRawBuffer rawdata(reg, sqlinfo);
1374
1375 for (Int_t n = 0; n < NumChilds(); n++) {
1377 child->PerformConversion(reg, &rawdata, nullptr /*cl->GetName()*/);
1378 }
1379
1380 res = rawdata.IsAnyData();
1381 }
1382
1383 if (registerobj)
1384 reg->AddRegCmd(objid, cl);
1385
1386 reg->fCurrentObjId = oldid;
1387 reg->fCurrentObjClass = oldcl;
1388
1389 return res;
1390}
1391
1392////////////////////////////////////////////////////////////////////////////////
1393/// this function verify object child elements and
1394/// calls transformation to class table
1395
1397{
1398 if (fChilds.GetLast() != 1)
1399 return kFALSE;
1400
1401 TSQLStructure *s_ver = GetChild(0);
1402
1403 TSQLStructure *s_info = GetChild(1);
1404
1405 if (!CheckNormalClassPair(s_ver, s_info))
1406 return kFALSE;
1407
1408 return s_info->StoreClassInNormalForm(reg);
1409}
1410
1411////////////////////////////////////////////////////////////////////////////////
1412/// produces data for complete class table
1413/// where not possible, raw data for some elements are created
1414
1416{
1417 TClass *cl = nullptr;
1418 Version_t version = 0;
1419 if (!GetClassInfo(cl, version))
1420 return kFALSE;
1421 if (!cl)
1422 return kFALSE;
1423
1424 TSQLClassInfo *sqlinfo = reg->fFile->RequestSQLClassInfo(cl->GetName(), version);
1425
1426 TSQLTableData columns(reg->fFile, sqlinfo);
1427 // Bool_t needblob = kFALSE;
1428
1429 TSqlRawBuffer rawdata(reg, sqlinfo);
1430
1431 // Int_t currrawid = 0;
1432
1433 // add first column with object id
1434 columns.AddColumn(reg->fFile->SQLObjectIdColumn(), reg->fCurrentObjId);
1435
1436 for (Int_t n = 0; n <= fChilds.GetLast(); n++) {
1438 TStreamerElement *elem = child->GetElement();
1439
1440 if (!elem) {
1441 Error("StoreClassInNormalForm", "CAN NOT BE");
1442 continue;
1443 }
1444
1445 if (child->StoreElementInNormalForm(reg, &columns))
1446 continue;
1447
1448 Int_t columntyp = DefineElementColumnType(elem, reg->fFile);
1449 if ((columntyp != kColRawData) && (columntyp != kColObjectArray)) {
1450 Error("StoreClassInNormalForm", "Element %s typ=%d has problem with normal store ", elem->GetName(),
1451 columntyp);
1452 continue;
1453 }
1454
1455 Bool_t doblobs = kTRUE;
1456
1457 Int_t blobid = rawdata.fRawId; // keep id of first raw, used in class table
1458
1459 if (columntyp == kColObjectArray)
1460 if (child->TryConvertObjectArray(reg, &rawdata))
1461 doblobs = kFALSE;
1462
1463 if (doblobs)
1464 child->PerformConversion(reg, &rawdata, elem->GetName(), kFALSE);
1465
1466 if (blobid == rawdata.fRawId)
1467 blobid = -1; // no data for blob was created
1468 else {
1469 // reg->fFile->CreateRawTable(sqlinfo);
1470 // blobid = currrawid; // column will contain first raw id
1471 // reg->ConvertBlobs(&blobs, sqlinfo, currrawid);
1472 // needblob = kTRUE;
1473 }
1474 // blobs.Delete();
1475
1476 TString blobname = elem->GetName();
1477 if (reg->fFile->GetUseSuffixes())
1478 blobname += sqlio::RawSuffix;
1479
1480 columns.AddColumn(blobname, blobid);
1481 }
1482
1483 reg->fFile->CreateClassTable(sqlinfo, columns.TakeColInfos());
1484
1485 reg->InsertToNormalTable(&columns, sqlinfo);
1486
1487 return kTRUE;
1488}
1489
1490////////////////////////////////////////////////////////////////////////////////
1491/// produce string with complete index like [1][2][0]
1492
1494{
1495 TString res;
1496 if (!elem || (elem->GetArrayLength() == 0))
1497 return res;
1498
1499 for (Int_t ndim = elem->GetArrayDim() - 1; ndim >= 0; ndim--) {
1500 Int_t ix = index % elem->GetMaxIndex(ndim);
1501 index = index / elem->GetMaxIndex(ndim);
1502 TString buf;
1503 buf.Form("%s%d%s", "[", ix, "]");
1504 res = buf + res;
1505 }
1506 return res;
1507}
1508
1509////////////////////////////////////////////////////////////////////////////////
1510/// tries to store element data in column
1511
1513{
1514 TStreamerElement *elem = GetElement();
1515 if (!elem)
1516 return kFALSE;
1517
1518 Int_t typ = elem->GetType();
1519
1520 Int_t columntyp = DefineElementColumnType(elem, reg->fFile);
1521
1522 if (gDebug > 4)
1523 std::cout << "Element " << elem->GetName() << " type = " << typ << " column = " << columntyp << std::endl;
1524
1525 TString colname = DefineElementColumnName(elem, reg->fFile);
1526
1527 if (columntyp == kColTString) {
1528 const char *value;
1529 if (!RecognizeTString(value))
1530 return kFALSE;
1531
1532 Int_t len = value ? strlen(value) : 0;
1533
1534 Int_t sizelimit = reg->fFile->SQLSmallTextTypeLimit();
1535
1536 const char *stype = reg->fFile->SQLSmallTextType();
1537
1538 if (len <= sizelimit)
1539 columns->AddColumn(colname.Data(), stype, value, kFALSE);
1540 else {
1541 Int_t strid = reg->AddLongString(value);
1542 TString buf = reg->fFile->CodeLongString(reg->fCurrentObjId, strid);
1543 columns->AddColumn(colname.Data(), stype, buf.Data(), kFALSE);
1544 }
1545
1546 return kTRUE;
1547 }
1548
1549 if (columntyp == kColParent) {
1550 Long64_t objid = reg->fCurrentObjId;
1551 TClass *basecl = elem->GetClassPointer();
1552 Int_t resversion = basecl->GetClassVersion();
1553 if (!StoreObject(reg, objid, basecl, kFALSE))
1554 resversion = -1;
1555 columns->AddColumn(colname.Data(), resversion);
1556 return kTRUE;
1557 }
1558
1559 if (columntyp == kColObject) {
1560
1561 Long64_t objid = -1;
1562
1563 if (NumChilds() == 1) {
1565
1566 if (child->GetType() == kSqlObject) {
1567 objid = child->DefineObjectId(kFALSE);
1568 if (!child->StoreObject(reg, objid, child->GetObjectClass()))
1569 return kFALSE;
1570 } else if (child->GetType() == kSqlPointer) {
1571 TString sobjid = child->GetValue();
1572 if (sobjid.Length() > 0)
1573 objid = sqlio::atol64(sobjid.Data());
1574 }
1575 }
1576
1577 if (objid < 0) {
1578 // std::cout << "!!!! Not standard " << elem->GetName() << " class = " << elem->GetClassPointer()->GetName() <<
1579 // std::endl;
1580 objid = reg->GetNextObjId();
1581 if (!StoreObject(reg, objid, elem->GetClassPointer()))
1582 objid = -1; // this is a case, when no data was stored for this object
1583 }
1584
1585 columns->AddColumn(colname.Data(), objid);
1586 return kTRUE;
1587 }
1588
1589 if (columntyp == kColNormObject) {
1590
1591 if (NumChilds() != 1) {
1592 Error("kColNormObject", "NumChilds()=%d", NumChilds());
1593 PrintLevel(20);
1594 return kFALSE;
1595 }
1597 if ((child->GetType() != kSqlPointer) && (child->GetType() != kSqlObject))
1598 return kFALSE;
1599
1600 Bool_t normal = kTRUE;
1601
1602 Long64_t objid = -1;
1603
1604 if (child->GetType() == kSqlObject) {
1605 objid = child->DefineObjectId(kFALSE);
1606 normal = child->StoreObject(reg, objid, child->GetObjectClass());
1607 } else {
1608 objid = child->DefineObjectId(kFALSE);
1609 }
1610
1611 if (!normal) {
1612 Error("kColNormObject", "child->StoreObject fails");
1613 return kFALSE;
1614 }
1615
1616 columns->AddColumn(colname.Data(), objid);
1617 return kTRUE;
1618 }
1619
1620 if (columntyp == kColNormObjectArray) {
1621
1622 if (elem->GetArrayLength() != NumChilds())
1623 return kFALSE;
1624
1625 for (Int_t index = 0; index < NumChilds(); index++) {
1627 if ((child->GetType() != kSqlPointer) && (child->GetType() != kSqlObject))
1628 return kFALSE;
1629 Bool_t normal = kTRUE;
1630
1631 Long64_t objid = child->DefineObjectId(kFALSE);
1632
1633 if (child->GetType() == kSqlObject)
1634 normal = child->StoreObject(reg, objid, child->GetObjectClass());
1635
1636 if (!normal)
1637 return kFALSE;
1638
1639 colname = DefineElementColumnName(elem, reg->fFile, index);
1640
1641 columns->AddColumn(colname.Data(), objid);
1642 }
1643 return kTRUE;
1644 }
1645
1646 if (columntyp == kColObjectPtr) {
1647 if (NumChilds() != 1)
1648 return kFALSE;
1650 if ((child->GetType() != kSqlPointer) && (child->GetType() != kSqlObject))
1651 return kFALSE;
1652
1653 Bool_t normal = kTRUE;
1654 Long64_t objid = -1;
1655
1656 if (child->GetType() == kSqlObject) {
1657 objid = child->DefineObjectId(kFALSE);
1658 normal = child->StoreObject(reg, objid, child->GetObjectClass());
1659 }
1660
1661 if (!normal)
1662 return kFALSE;
1663
1664 columns->AddColumn(colname.Data(), objid);
1665 return kTRUE;
1666 }
1667
1668 if (columntyp == kColSimple) {
1669
1670 // only child should exist for element
1671 if (NumChilds() != 1) {
1672 Error("StoreElementInNormalForm", "Unexpected number %d for simple element %s", NumChilds(), elem->GetName());
1673 return kFALSE;
1674 }
1675
1677 if (child->GetType() != kSqlValue)
1678 return kFALSE;
1679
1680 const char *value = child->GetValue();
1681 if (!value)
1682 return kFALSE;
1683
1684 const char *sqltype = reg->fFile->SQLCompatibleType(typ);
1685
1686 columns->AddColumn(colname.Data(), sqltype, value, IsNumericType(typ));
1687
1688 return kTRUE;
1689 }
1690
1691 if (columntyp == kColSimpleArray) {
1692 // number of items should be exactly equal to number of children
1693
1694 if (NumChilds() != 1) {
1695 Error("StoreElementInNormalForm", "In fixed array %s only array node should be", elem->GetName());
1696 return kFALSE;
1697 }
1698 TSQLStructure *arr = GetChild(0);
1699
1700 const char *sqltype = reg->fFile->SQLCompatibleType(typ % 20);
1701
1702 for (Int_t n = 0; n < arr->NumChilds(); n++) {
1703 TSQLStructure *child = arr->GetChild(n);
1704 if (child->GetType() != kSqlValue)
1705 return kFALSE;
1706
1707 const char *value = child->GetValue();
1708 if (!value)
1709 return kFALSE;
1710
1711 Int_t index = child->GetArrayIndex();
1712 Int_t last = index + child->GetRepeatCounter();
1713
1714 while (index < last) {
1715 colname = DefineElementColumnName(elem, reg->fFile, index);
1716 columns->AddColumn(colname.Data(), sqltype, value, kTRUE);
1717 index++;
1718 }
1719 }
1720 return kTRUE;
1721 }
1722
1723 return kFALSE;
1724}
1725
1726////////////////////////////////////////////////////////////////////////////////
1727/// tries to write array of objects as list of object references
1728/// in _streamer_ table, while objects itself will be stored in
1729/// other tables. If not successful, object data will be stored
1730/// in _streamer_ table
1731
1733{
1734 TStreamerElement *elem = GetElement();
1735 if (!elem)
1736 return kFALSE;
1737
1738 if (NumChilds() % 2 != 0)
1739 return kFALSE;
1740
1741 Int_t indx = 0;
1742
1743 while (indx < NumChilds()) {
1744 TSQLStructure *s_ver = GetChild(indx++);
1745 TSQLStructure *s_info = GetChild(indx++);
1746 if (!CheckNormalClassPair(s_ver, s_info))
1747 return kFALSE;
1748 }
1749
1750 indx = 0;
1751 const char *ns = reg->fFile->SQLNameSeparator();
1752
1753 while (indx < NumChilds() - 1) {
1754 indx++; // TSQLStructure* s_ver = GetChild(indx++);
1755 TSQLStructure *s_info = GetChild(indx++);
1756 TClass *cl = nullptr;
1757 Version_t version = 0;
1758 if (!s_info->GetClassInfo(cl, version))
1759 return kFALSE;
1760 Long64_t objid = reg->GetNextObjId();
1761 if (!s_info->StoreObject(reg, objid, cl))
1762 objid = -1; // this is a case, when no data was stored for this object
1763
1764 TString sobjid;
1765 sobjid.Form("%lld", objid);
1766
1767 blobs->AddLine(sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns);
1768 }
1769
1770 return kTRUE;
1771}
1772
1773////////////////////////////////////////////////////////////////////////////////
1774/// check if pair of two element corresponds
1775/// to start of object, stored in normal form
1776
1778{
1779 if (!s_ver || !s_info || (s_ver->GetType() != kSqlVersion))
1780 return kFALSE;
1781
1782 TClass *ver_cl = s_ver->GetVersionClass();
1783
1784 TClass *info_cl = nullptr;
1785 Version_t info_ver = 0;
1786 if (!s_info->GetClassInfo(info_cl, info_ver))
1787 return kFALSE;
1788
1789 if (!ver_cl || !info_cl || (ver_cl != info_cl) || (ver_cl->GetClassVersion() != info_ver))
1790 return kFALSE;
1791
1792 return kTRUE;
1793}
1794
1795////////////////////////////////////////////////////////////////////////////////
1796/// store data of TObject in special table
1797/// workaround custom TObject streamer
1798
1800{
1801 // check if it is really Looks like TObject data
1802 if ((NumChilds() < 3) || (NumChilds() > 4))
1803 return kFALSE;
1804
1805 TSQLStructure *str_ver = GetChild(0);
1806 TSQLStructure *str_id = GetChild(1);
1807 TSQLStructure *str_bits = GetChild(2);
1808 TSQLStructure *str_prid = GetChild(3);
1809
1810 if (str_ver->GetType() != kSqlVersion)
1811 return kFALSE;
1812 if ((str_id->GetType() != kSqlValue) || (str_id->GetValueType() != sqlio::UInt))
1813 return kFALSE;
1814 if ((str_bits->GetType() != kSqlValue) || (str_bits->GetValueType() != sqlio::UInt))
1815 return kFALSE;
1816 if (str_prid)
1817 if ((str_prid->GetType() != kSqlValue) || (str_prid->GetValueType() != sqlio::UShort))
1818 return kFALSE;
1819
1820 TSQLClassInfo *sqlinfo = reg->fFile->RequestSQLClassInfo(TObject::Class());
1821
1822 if (!sqlinfo)
1823 return kFALSE;
1824
1825 TSQLTableData columns(reg->fFile, sqlinfo);
1826
1827 const char *uinttype = reg->fFile->SQLCompatibleType(TStreamerInfo::kUInt);
1828
1829 columns.AddColumn(reg->fFile->SQLObjectIdColumn(), reg->fCurrentObjId);
1830
1831 columns.AddColumn(sqlio::TObjectUniqueId, uinttype, str_id->GetValue(), kTRUE);
1832 columns.AddColumn(sqlio::TObjectBits, uinttype, str_bits->GetValue(), kTRUE);
1833 columns.AddColumn(sqlio::TObjectProcessId, "CHAR(3)", (str_prid ? str_prid->GetValue() : ""), kFALSE);
1834
1835 reg->fFile->CreateClassTable(sqlinfo, columns.TakeColInfos());
1836
1837 reg->InsertToNormalTable(&columns, sqlinfo);
1838
1839 return kTRUE;
1840}
1841
1842////////////////////////////////////////////////////////////////////////////////
1843/// store data of TString in special table
1844/// it is required when TString stored as pointer and reference to it possible
1845
1847{
1848 const char *value = nullptr;
1849 if (!RecognizeTString(value))
1850 return kFALSE;
1851
1852 TSQLClassInfo *sqlinfo = reg->fFile->RequestSQLClassInfo(TString::Class());
1853 if (!sqlinfo)
1854 return kFALSE;
1855
1856 TSQLTableData columns(reg->fFile, sqlinfo);
1857
1858 columns.AddColumn(reg->fFile->SQLObjectIdColumn(), reg->fCurrentObjId);
1859 columns.AddColumn(sqlio::TStringValue, reg->fFile->SQLBigTextType(), value, kFALSE);
1860
1861 reg->fFile->CreateClassTable(sqlinfo, columns.TakeColInfos());
1862
1863 reg->InsertToNormalTable(&columns, sqlinfo);
1864 return kTRUE;
1865}
1866
1867////////////////////////////////////////////////////////////////////////////////
1868/// prove that structure contains TString data
1869
1871{
1872 value = nullptr;
1873
1874 if ((NumChilds() == 0) || (NumChilds() > 3))
1875 return kFALSE;
1876
1877 TSQLStructure *len = nullptr, *lenbig = nullptr, *chars = nullptr;
1878 for (Int_t n = 0; n < NumChilds(); n++) {
1879 TSQLStructure *curr = GetChild(n);
1880 if (curr->fType != kSqlValue)
1881 return kFALSE;
1882 if (curr->fPointer == sqlio::UChar) {
1883 if (!len)
1884 len = curr;
1885 else
1886 return kFALSE;
1887 } else if (curr->fPointer == sqlio::Int) {
1888 if (!lenbig)
1889 lenbig = curr;
1890 else
1891 return kFALSE;
1892 } else if (curr->fPointer == sqlio::CharStar) {
1893 if (!chars)
1894 chars = curr;
1895 else
1896 return kFALSE;
1897 } else
1898 return kFALSE;
1899 }
1900
1901 if (!len)
1902 return kFALSE;
1903 if (lenbig && !chars)
1904 return kFALSE;
1905
1906 if (chars)
1907 value = chars->GetValue();
1908
1909 return kTRUE;
1910}
1911
1912////////////////////////////////////////////////////////////////////////////////
1913/// defines which kind of column can be assigned for this element
1914/// Possible cases
1915/// kColSimple - basic data type
1916/// kColSimpleArray - fixed array of basic types
1917/// kColParent - parent class
1918/// kColObject - object as data member
1919/// kColObjectPtr - object as pointer
1920/// kColTString - TString
1921/// kColRawData - anything else as raw data
1922
1924{
1925 if (!elem)
1926 return kColUnknown;
1927
1928 Int_t typ = elem->GetType();
1929
1930 if (typ == TStreamerInfo::kMissing)
1931 return kColRawData;
1932
1933 if ((typ > 0) && (typ < 20) && (typ != TStreamerInfo::kCharStar))
1934 return kColSimple;
1935
1936 if ((typ > TStreamerInfo::kOffsetL) && (typ < TStreamerInfo::kOffsetP))
1937 if ((f->GetArrayLimit() < 0) || (elem->GetArrayLength() <= f->GetArrayLimit()))
1938 return kColSimpleArray;
1939
1940 if (typ == TStreamerInfo::kTObject) {
1942 return kColParent;
1943 else
1944 return kColObject;
1945 }
1946
1947 if (typ == TStreamerInfo::kTNamed) {
1949 return kColParent;
1950 else
1951 return kColObject;
1952 }
1953
1954 if (typ == TStreamerInfo::kTString)
1955 return kColTString;
1956
1957 if (typ == TStreamerInfo::kBase)
1958 return kColParent;
1959
1960 if (typ == TStreamerInfo::kSTL)
1962 return kColParent;
1963
1964 // this is workaround
1965 // these two tags stored with WriteFastArray, but read with cl->Streamer()
1966 if ((typ == TStreamerInfo::kObject) || (typ == TStreamerInfo::kAny)) {
1967 if (elem->GetArrayLength() == 0)
1968 return kColObject;
1969 else if (!elem->GetStreamer())
1970 return kColObjectArray;
1971 }
1972
1973 if ((typ == TStreamerInfo::kObject) || (typ == TStreamerInfo::kAny) || (typ == TStreamerInfo::kAnyp) ||
1974 (typ == TStreamerInfo::kObjectp) || (typ == TStreamerInfo::kAnyP) || (typ == TStreamerInfo::kObjectP)) {
1975 if ((elem->GetArrayLength() == 0) || elem->GetStreamer())
1976 return kColNormObject;
1977 else
1978 return kColNormObjectArray;
1979 }
1980
1987 if (elem->GetStreamer())
1988 return kColNormObject;
1989 else
1990 return kColNormObjectArray;
1991 }
1992
1993 if ((typ == TStreamerInfo::kObject) || (typ == TStreamerInfo::kAny) || (typ == TStreamerInfo::kAnyp) ||
1994 (typ == TStreamerInfo::kObjectp) || (typ == TStreamerInfo::kSTL)) {
1995 if (elem->GetArrayLength() == 0)
1996 return kColObject;
1997 else if (!elem->GetStreamer())
1998 return kColObjectArray;
1999 }
2000
2001 if (((typ == TStreamerInfo::kAnyP) || (typ == TStreamerInfo::kObjectP)) && (elem->GetArrayDim() == 0))
2002 return kColObjectPtr;
2003
2004 // if ((typ==TStreamerInfo::kSTLp) &&
2005 // (elem->GetArrayDim()==0)) {
2006 // TStreamerSTL* stl = dynamic_cast<TStreamerSTL*> (elem);
2007 // if ((stl!=0) && (dynamic_cast<TStreamerSTLstring*>(elem)==0))
2008 // return kColObjectPtr;
2009 // }
2010
2011 return kColRawData;
2012}
2013
2014////////////////////////////////////////////////////////////////////////////////
2015/// returns name of the column in class table for that element
2016
2018{
2019 TString colname = "";
2020
2021 Int_t coltype = DefineElementColumnType(elem, f);
2022 if (coltype == kColUnknown)
2023 return colname;
2024
2025 const char *elemname = elem->GetName();
2026
2027 switch (coltype) {
2028 case kColSimple: {
2029 colname = elemname;
2030 if (f->GetUseSuffixes()) {
2031 colname += f->SQLNameSeparator();
2032 colname += GetSimpleTypeName(elem->GetType());
2033 }
2034 break;
2035 }
2036
2037 case kColSimpleArray: {
2038 colname = elemname;
2039 colname += MakeArrayIndex(elem, indx);
2040 break;
2041 }
2042
2043 case kColParent: {
2044 colname = elemname;
2045 if (f->GetUseSuffixes())
2046 colname += sqlio::ParentSuffix;
2047 break;
2048 }
2049
2050 case kColNormObject: {
2051 colname = elemname;
2052 if (f->GetUseSuffixes())
2053 colname += sqlio::ObjectSuffix;
2054 break;
2055 }
2056
2057 case kColNormObjectArray: {
2058 colname = elemname;
2059 colname += MakeArrayIndex(elem, indx);
2060 if (f->GetUseSuffixes())
2061 colname += sqlio::ObjectSuffix;
2062 break;
2063 }
2064
2065 case kColObject: {
2066 colname = elemname;
2067 if (f->GetUseSuffixes())
2068 colname += sqlio::ObjectSuffix;
2069 break;
2070 }
2071
2072 case kColObjectPtr: {
2073 colname = elemname;
2074 if (f->GetUseSuffixes())
2075 colname += sqlio::PointerSuffix;
2076 break;
2077 }
2078
2079 case kColTString: {
2080 colname = elem->GetName();
2081 if (f->GetUseSuffixes())
2082 colname += sqlio::StrSuffix;
2083 break;
2084 }
2085
2086 case kColRawData: {
2087 colname = elemname;
2088 if (f->GetUseSuffixes())
2089 colname += sqlio::RawSuffix;
2090 break;
2091 }
2092
2093 case kColObjectArray: {
2094 colname = elemname;
2095 if (f->GetUseSuffixes())
2096 colname += sqlio::RawSuffix;
2097 break;
2098 }
2099 }
2100
2101 return colname;
2102}
2103
2104////////////////////////////////////////////////////////////////////////////////
2105/// find column in TSQLObjectData object, which correspond to current element
2106
2108{
2109 TStreamerElement *elem = GetElement();
2110 if (!elem || !data)
2111 return kColUnknown;
2112
2113 Int_t coltype = DefineElementColumnType(elem, f);
2114
2115 if (gDebug > 4)
2116 std::cout << "TSQLStructure::LocateElementColumn " << elem->GetName() << " coltyp = " << coltype << " : "
2117 << elem->GetType() << " len = " << elem->GetArrayLength() << std::endl;
2118
2119 if (coltype == kColUnknown)
2120 return kColUnknown;
2121
2122 const char *elemname = elem->GetName();
2123 Bool_t located = kFALSE;
2124
2125 TString colname = DefineElementColumnName(elem, f);
2126
2127 if (gDebug > 4)
2128 std::cout << " colname = " << colname << " in " << data->GetInfo()->GetClassTableName() << std::endl;
2129
2130 switch (coltype) {
2131 case kColSimple: {
2132 located = data->LocateColumn(colname.Data());
2133 break;
2134 }
2135
2136 case kColSimpleArray: {
2137 located = data->LocateColumn(colname);
2138 break;
2139 }
2140
2141 case kColParent: {
2142 located = data->LocateColumn(colname.Data());
2143 if (located == kColUnknown)
2144 return kColUnknown;
2145
2146 Long64_t objid = DefineObjectId(kTRUE);
2147 const char *clname = elemname;
2148 Version_t version = atoi(data->GetValue());
2149
2150 // this is a case, when parent store nothing in the database
2151 if (version < 0)
2152 break;
2153
2154 // special treatment for TObject
2155 if (strcmp(clname, TObject::Class()->GetName()) == 0) {
2156 UnpackTObject(f, buf, data, objid, version);
2157 break;
2158 }
2159
2160 TSQLClassInfo *sqlinfo = f->FindSQLClassInfo(clname, version);
2161 if (!sqlinfo)
2162 return kColUnknown;
2163
2164 // this will indicate that streamer is completely custom
2165 if (sqlinfo->IsClassTableExist()) {
2166 data->AddUnpackInt(sqlio::Version, version);
2167 } else {
2168 TSQLObjectData *objdata = buf->SqlObjectData(objid, sqlinfo);
2169 if (!objdata || !objdata->PrepareForRawData())
2170 return kColUnknown;
2171 AddObjectData(objdata);
2172 }
2173
2174 break;
2175 }
2176
2177 // This is a case when streamer of object will be called directly.
2178 // Typically it happens when object is data member of the class.
2179 // Here we need to define class of object and if it was written by
2180 // normal streamer (via TStreamerInfo methods) or directly as blob.
2181 // When blob was used, blob data should be read.
2182 // In normal case only version is required. Other object data will be
2183 // read by TBufferSQL2::IncrementLevel method
2184 case kColObject: {
2185 located = data->LocateColumn(colname.Data());
2186 if (located == kColUnknown)
2187 return located;
2188
2189 const char *strobjid = data->GetValue();
2190 if (!strobjid)
2191 return kColUnknown;
2192
2193 Long64_t objid = sqlio::atol64(strobjid);
2194
2195 // when nothing was stored, nothing need to be read. skip
2196 if (objid < 0)
2197 break;
2198
2199 TString clname;
2200 Version_t version;
2201
2202 if (!buf->SqlObjectInfo(objid, clname, version))
2203 return kColUnknown;
2204
2205 // special treatment for TObject
2206 if (clname == TObject::Class()->GetName()) {
2207 UnpackTObject(f, buf, data, objid, version);
2208 break;
2209 }
2210
2211 TSQLClassInfo *sqlinfo = f->FindSQLClassInfo(clname.Data(), version);
2212 if (!sqlinfo)
2213 return kColUnknown;
2214
2215 if (sqlinfo->IsClassTableExist()) {
2216 data->AddUnpackInt(sqlio::Version, version);
2217 } else {
2218 TSQLObjectData *objdata = buf->SqlObjectData(objid, sqlinfo);
2219 if (!objdata || !objdata->PrepareForRawData())
2220 return kColUnknown;
2221 AddObjectData(objdata);
2222 }
2223
2224 // work around to store objid of object, which is memeber of class
2225 fValue = strobjid;
2226
2227 break;
2228 }
2229
2230 // this is case of pointer on any object
2231 // field contains objectid.
2232 // Object id, class of object and so on will be checked
2233 // when TBuffer::ReadObject method will be called
2234 case kColObjectPtr: {
2235 located = data->LocateColumn(colname.Data());
2236 break;
2237 }
2238
2239 // this is case of on object which is treated normally in TBuffer
2240 // field should contains objectid.
2241 // Object id, class of object and so on will be checked
2242 // when TBuffer::StreamObject method will be called
2243 case kColNormObject: {
2244 located = data->LocateColumn(colname.Data());
2245 break;
2246 }
2247
2248 case kColNormObjectArray: {
2249 located = data->LocateColumn(colname.Data());
2250 break;
2251 }
2252
2253 case kColTString: {
2254 located = data->LocateColumn(colname);
2255 if (located == kColUnknown)
2256 return located;
2257 const char *value = data->GetValue();
2258
2259 Long64_t objid = DefineObjectId(kTRUE);
2260 Int_t strid = f->IsLongStringCode(objid, value);
2261
2262 TString buf2;
2263
2264 // if special prefix found, than try get such string
2265 if (strid > 0)
2266 if (f->GetLongString(objid, strid, buf2))
2267 value = buf2.Data();
2268
2269 Int_t len = !value ? 0 : strlen(value);
2270 if (len < 255) {
2271 data->AddUnpackInt(sqlio::UChar, len);
2272 } else {
2273 data->AddUnpackInt(sqlio::UChar, 255);
2274 data->AddUnpackInt(sqlio::Int, len);
2275 }
2276 if (len > 0)
2277 data->AddUnpack(sqlio::CharStar, value);
2278 break;
2279 }
2280
2281 case kColRawData: {
2282 located = data->LocateColumn(colname.Data(), kTRUE);
2283 break;
2284 }
2285
2286 case kColObjectArray: {
2287 located = data->LocateColumn(colname.Data(), kTRUE);
2288 break;
2289 }
2290 }
2291
2292 if (!located)
2293 coltype = kColUnknown;
2294
2295 return coltype;
2296}
2297
2298////////////////////////////////////////////////////////////////////////////////
2299/// Unpack TObject data in form, accepted by custom TObject streamer
2300
2301Bool_t
2303{
2304 TSQLClassInfo *sqlinfo = f->FindSQLClassInfo(TObject::Class()->GetName(), clversion);
2305 if (!sqlinfo)
2306 return kFALSE;
2307
2308 TSQLObjectData *tobjdata = buf->SqlObjectData(objid, sqlinfo);
2309 if (!tobjdata)
2310 return kFALSE;
2311
2312 data->AddUnpackInt(sqlio::Version, clversion);
2313
2315 data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
2316 tobjdata->ShiftToNextValue();
2317
2319 data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
2320 tobjdata->ShiftToNextValue();
2321
2323 const char *value = tobjdata->GetValue();
2324 if (value && (strlen(value) > 0))
2325 data->AddUnpack(sqlio::UShort, value);
2326
2327 delete tobjdata;
2328
2329 return kTRUE;
2330}
2331
2332////////////////////////////////////////////////////////////////////////////////
2333/// Unpack TString data in form, accepted by custom TString streamer
2334
2335Bool_t
2337{
2338 TSQLClassInfo *sqlinfo = f->FindSQLClassInfo(TString::Class()->GetName(), clversion);
2339 if (!sqlinfo)
2340 return kFALSE;
2341
2342 TSQLObjectData *tstringdata = buf->SqlObjectData(objid, sqlinfo);
2343 if (!tstringdata)
2344 return kFALSE;
2345
2346 tstringdata->LocateColumn(sqlio::TStringValue);
2347
2348 const char *value = tstringdata->GetValue();
2349
2350 Int_t len = !value ? 0 : strlen(value);
2351 if (len < 255) {
2352 data->AddUnpackInt(sqlio::UChar, len);
2353 } else {
2354 data->AddUnpackInt(sqlio::UChar, 255);
2355 data->AddUnpackInt(sqlio::Int, len);
2356 }
2357 if (len > 0)
2358 data->AddUnpack(sqlio::CharStar, value);
2359
2360 delete tstringdata;
2361
2362 return kTRUE;
2363}
2364
2365////////////////////////////////////////////////////////////////////////////////
2366/// adds quotes around string value and replaces some special symbols
2367
2368void TSQLStructure::AddStrBrackets(TString &s, const char *quote)
2369{
2370 if (strcmp(quote, "\"") == 0)
2371 s.ReplaceAll("\"", "\\\"");
2372 else
2373 s.ReplaceAll("'", "''");
2374 s.Prepend(quote);
2375 s.Append(quote);
2376}
#define f(i)
Definition RSha256.hxx:104
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
short Version_t
Definition RtypesCore.h:65
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:85
#define ClassImp(name)
Definition Rtypes.h:377
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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 child
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 GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:597
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
Converts data to SQL statements or read data from SQL tables.
Definition TBufferSQL2.h:27
Bool_t SqlObjectInfo(Long64_t objid, TString &clname, Version_t &version)
Returns object info like classname and version Should be taken from buffer, which is produced in the ...
TSQLObjectData * SqlObjectData(Long64_t objid, TSQLClassInfo *sqlinfo)
Creates TSQLObjectData for specified object id and specified class.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
Version_t GetClassVersion() const
Definition TClass.h:420
const char * GetName() const override
Return name of this collection.
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition TMap.h:40
void Add(TObject *obj) override
This function may not be used (but we need to provide it since it is a pure virtual in TCollection).
Definition TMap.cxx:54
void DeleteValues()
Remove all (key,value) pairs from the map AND delete the values when they are allocated on the heap.
Definition TMap.cxx:151
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition TMap.cxx:236
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
Int_t GetLast() const override
Return index of last object in array.
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:438
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
static TClass * Class()
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:524
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
const char * GetSQLName() const
Contains information about tables specific to one class and version.
Bool_t IsClassTableExist() const
const char * GetClassTableName() const
const char * GetRawTableName() const
TString fValue
! value of the table column
TSQLColumnData(const char *name, const char *sqltype, const char *value, Bool_t numeric)
normal constructor of TSQLColumnData class specifies name, type and value for one column
Access an SQL db via the TFile interface.
Definition TSQLFile.h:30
const char * SQLIdentifierQuote() const
Definition TSQLFile.h:136
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.
const char * SQLValueQuote() const
Definition TSQLFile.h:143
Bool_t IsMySQL() const
checks, if MySQL database
Definition TSQLFile.cxx:467
Bool_t IsOracle() const
checks, if Oracle database
Definition TSQLFile.cxx:477
Int_t SQLSmallTextTypeLimit() const
Definition TSQLFile.h:133
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
Int_t SQLMaxIdentifierLength()
returns maximum allowed length of identifiers
Bool_t IsODBC() const
checks, if ODBC driver used for database connection
Definition TSQLFile.cxx:487
Bool_t VerifyLongStringTable()
Checks that table for big strings is exists If not, will be created.
TSQLObjectData is used in TBufferSQL2 class in reading procedure.
Bool_t LocateColumn(const char *colname, Bool_t isblob=kFALSE)
locate column of that name in results
void ShiftToNextValue()
shift to next column or next row in blob data
const char * GetValue() const
Bool_t PrepareForRawData()
prepare to read data from raw table
virtual Bool_t NextIteration()=0
virtual Bool_t SetString(Int_t, const char *, Int_t=256)
virtual Bool_t Process()=0
virtual Bool_t SetInt(Int_t, Int_t)
virtual Bool_t SetLong64(Int_t, Long64_t)
This is hierarchical structure, which is created when data is written by TBufferSQL2.
Bool_t RecognizeTString(const char *&value)
prove that structure contains TString data
TSQLStructure * GetParent() const
Int_t LocateElementColumn(TSQLFile *f, TBufferSQL2 *buf, TSQLObjectData *data)
find column in TSQLObjectData object, which correspond to current element
TClass * GetObjectClass() const
return object class if type kSqlObject
void SetValue(const char *value, const char *tname=nullptr)
set structure type as kSqlValue
Bool_t TryConvertObjectArray(TSqlRegistry *reg, TSqlRawBuffer *blobs)
tries to write array of objects as list of object references in streamer table, while objects itself ...
static void AddStrBrackets(TString &s, const char *quote)
adds quotes around string value and replaces some special symbols
void Add(TSQLStructure *child)
Add child structure.
void AddVersion(const TClass *cl, Int_t version=-100)
add child as version
void SetVersion(const TClass *cl, Int_t version=-100)
set structure type as kSqlVersion
const void * fPointer
TObjArray fChilds
void SetObjectPointer(Long64_t ptrid)
set structure type as kSqlPointer
void SetArray(Int_t sz=-1)
Set structure as array element.
static Bool_t IsNumericType(Int_t typ)
defines if value is numeric and not requires quotes when writing
Int_t GetElementNumber() const
returns number of TStremerElement in TStreamerInfo
TSQLObjectData * GetObjectData(Bool_t search=false)
searches for objects data
TStreamerInfo * GetStreamerInfo() const
return TStreamerInfo* if type is kSqlStreamerInfo
void PerformConversion(TSqlRegistry *reg, TSqlRawBuffer *blobs, const char *topname, Bool_t useblob=kFALSE)
perform conversion of structure to sql statements first tries convert it to normal form if fails,...
Bool_t StoreTObject(TSqlRegistry *reg)
store data of TObject in special table workaround custom TObject streamer
TSQLStructure * GetChild(Int_t n) const
return child structure of index n
Bool_t GetClassInfo(TClass *&cl, Version_t &version)
provides class info if structure kSqlStreamerInfo or kSqlCustomClass
void SetCustomClass(const TClass *cl, Version_t version)
set structure type as kSqlCustomClass
const char * GetValue() const
returns value for different structure kinds has different sense For kSqlVersion it version,...
static Bool_t UnpackTString(TSQLFile *f, TBufferSQL2 *buf, TSQLObjectData *data, Long64_t objid, Int_t clversion)
Unpack TString data in form, accepted by custom TString streamer.
static Int_t DefineElementColumnType(TStreamerElement *elem, TSQLFile *f)
defines which kind of column can be assigned for this element Possible cases kColSimple - basic data ...
Long64_t FindMaxObjectId()
define maximum reference id, used for objects
void AddValue(const char *value, const char *tname=nullptr)
Add child structure as value.
Bool_t StoreObjectInNormalForm(TSqlRegistry *reg)
this function verify object child elements and calls transformation to class table
void SetStreamerInfo(const TStreamerInfo *info)
set structure type as kSqlStreamerInfo
void AddObjectData(TSQLObjectData *objdata)
add element with pointer to object data
void SetArrayIndex(Int_t indx, Int_t cnt=1)
set array index for this structure
Int_t GetType() const
Bool_t StoreClassInNormalForm(TSqlRegistry *reg)
produces data for complete class table where not possible, raw data for some elements are created
static TString MakeArrayIndex(TStreamerElement *elem, Int_t n)
produce string with complete index like [1][2][0]
Version_t GetCustomClassVersion() const
return custom class version if structures is kSqlCustomClass
static Bool_t UnpackTObject(TSQLFile *f, TBufferSQL2 *buf, TSQLObjectData *data, Long64_t objid, Int_t clversion)
Unpack TObject data in form, accepted by custom TObject streamer.
Bool_t StoreObject(TSqlRegistry *reg, Long64_t objid, TClass *cl, Bool_t registerobj=kTRUE)
convert object data to sql statements if normal (column-wise) representation is not possible,...
void ChangeValueOnly(const char *value)
change value of this structure used as "workaround" to keep object id in kSqlElement node
Bool_t ConvertToTables(TSQLFile *f, Long64_t keyid, TObjArray *cmds)
Convert structure to sql statements This function is called immediately after TBufferSQL2 produces th...
void Print(Option_t *option="") const override
print content of complete structure
void SetCustomElement(TStreamerElement *elem)
set structure type as kSqlCustomElement
const char * GetValueType() const
return value type if structure is kSqlValue
static TString DefineElementColumnName(TStreamerElement *elem, TSQLFile *f, Int_t indx=0)
returns name of the column in class table for that element
void SetObjectData(TSQLObjectData *objdata)
set element to be used for object data
void SetObjectRef(Long64_t refid, const TClass *cl)
set structure type as kSqlObject
Long64_t DefineObjectId(Bool_t recursive=kTRUE)
defines current object id, to which this structure belong make life complicated, because some objects...
TStreamerElement * GetElement() const
return TStremerElement* if type is kSqlElement
TClass * GetVersionClass() const
return class for version tag if type is kSqlVersion
void PrintLevel(Int_t level) const
print content of current structure
static const char * GetSimpleTypeName(Int_t typ)
provides name for basic types used as suffix for column name or field suffix in raw table
Bool_t StoreElementInNormalForm(TSqlRegistry *reg, TSQLTableData *columns)
tries to store element data in column
Bool_t CheckNormalClassPair(TSQLStructure *vers, TSQLStructure *info)
check if pair of two element corresponds to start of object, stored in normal form
Int_t NumChilds() const
number of child structures
TClass * GetCustomClass() const
return element custom class if structures is kSqlCustomClass
~TSQLStructure() override
destructor
Bool_t StoreTString(TSqlRegistry *reg)
store data of TString in special table it is required when TString stored as pointer and reference to...
void SetClassStreamer(const TClass *cl)
set structure type as kSqlClassStreamer
void SetStreamerElement(const TStreamerElement *elem, Int_t number)
set structure type as kSqlElement
void ChildArrayIndex(Int_t index, Int_t cnt=1)
set array index for last child element if (cnt<=1) return;
void AddColumn(const char *name, Long64_t value)
Add INT column to list of columns.
TString DefineSQLName(const char *fullname)
produce suitable name for column, taking into account length limitation
~TSQLTableData() override
destructor
Bool_t HasSQLName(const char *sqlname)
checks if columns list already has that sql name
const char * GetColumn(Int_t n)
return column value
Bool_t IsNumeric(Int_t n)
identifies if column has numeric value
TObjArray fColumns
! collection of columns
Int_t GetNumColumns()
returns number of columns in provided set
TSQLFile * fFile
!
TObjArray * fColInfos
! array with TSQLClassColumnInfo, used later for TSQLClassInfo
TSQLTableData(TSQLFile *f=nullptr, TSQLClassInfo *info=nullptr)
normal constructor
TObjArray * TakeColInfos()
take ownership over colinfos
TSQLStatement * fBlobStmt
TSQLStatement * fNormStmt
TSQLClassInfo * fInfo
~TSqlCmdsBuffer() override
TSqlCmdsBuffer(TSQLFile *f, TSQLClassInfo *info)
void AddValues(Bool_t isnorm, const char *values)
Bool_t IsAnyData() const
~TSqlRawBuffer() override
TSQLClassInfo * fInfo
const char * fValueQuote
TSqlRawBuffer(TSqlRegistry *reg, TSQLClassInfo *sqlinfo)
TSqlCmdsBuffer * fCmdBuf
void AddLine(const char *name, const char *value, const char *topname=nullptr, const char *ns=nullptr)
~TSqlRegistry() override
Bool_t InsertToNormalTableOracle(TSQLTableData *columns, TSQLClassInfo *sqlinfo)
TSqlCmdsBuffer * GetCmdsBuffer(TSQLClassInfo *sqlinfo)
Long64_t fFirstObjId
TObjArray fLongStrValues
TObjArray fRegValues
Long64_t fLastObjId
Long64_t fCurrentObjId
void ConvertPoolValues()
TClass * fCurrentObjClass
TSQLStatement * fRegStmt
TSQLFile * fFile
void InsertToNormalTable(TSQLTableData *columns, TSQLClassInfo *sqlinfo)
void AddRegCmd(Long64_t objid, TClass *cl)
Long64_t GetNextObjId()
void AddSqlCmd(const char *query)
void ConvertSqlValues(TObjArray &values, const char *tablename)
Int_t AddLongString(const char *strvalue)
TObjArray * fCmds
static TClass * Class()
Int_t GetType() const
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetArrayDim() const
TMemberStreamer * GetStreamer() const
Return the local streamer object.
Int_t GetArrayLength() const
Int_t GetMaxIndex(Int_t i) const
Describes a persistent version of a class.
Int_t GetClassVersion() const override
@ kUChar
Equal to TDataType's kchar.
TClass * GetClass() const override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition TString.cxx:1152
TString & Prepend(const char *cs)
Definition TString.h:673
TString & Append(const char *cs)
Definition TString.h:572
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
static TClass * Class()
Long64_t Atoll() const
Return long long value of string.
Definition TString.cxx:2014
const Int_t n
Definition legend1.C:16
const char * cfg_UseIndexes
const char * DT_UUID
const char * KT_Name
const char * StringsTable
const char * KT_Title
const Int_t Ids_RootDir
const Int_t Ids_TSQLFile
const char * Long
const char * ULong
const char * ObjectsTableIndex
const char * ObjectSuffix
const char * KT_Cycle
const char * KeysTableIndex
const char * Float
const char * StrSuffix
const char * BT_Value
const char * OT_Version
const Int_t Ids_NullPtr
const char * KeysTable
Long64_t atol64(const char *value)
const char * TStringValue
const char * ObjectRef
const char * cfg_TablesType
const char * IdsTable
const Int_t Ids_FirstObject
const char * False
const char * CT_Field
const char * Double
const char * CT_Value
const char * ObjectRef_Arr
const char * KT_Datetime
const Int_t Ids_FirstKey
const char * DT_Create
const char * ST_Value
const char * UChar
const Int_t Ids_StreamerInfos
const char * ParentSuffix
const char * cfg_ArrayLimit
const char * IT_SubID
const char * ObjectPtr
const char * ULong64
const char * IT_SQLName
const char * IndexSepar
const char * TObjectProcessId
const char * PointerSuffix
const char * OT_Class
const char * IdsTableIndex
const char * ObjectInst
const char * ConfigTable
const char * Version
const char * cfg_UseTransactions
const char * Short
const char * Int
const char * BT_Field
const char * cfg_LockingMode
const char * cfg_UseSufixes
const char * Long64
const char * IT_Type
const char * IT_TableID
const char * UInt
const char * TObjectBits
const char * RawSuffix
const char * IT_Info
const char * True
const char * ObjectsTable
const char * KT_Class
const char * Array
const char * UShort
const char * cfg_ModifyCounter
const char * cfg_Version
const char * TObjectUniqueId
const char * DT_Modified
const char * Bool
const char * LongStrPrefix
const char * Char
const char * CharStar
const char * IT_FullName