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