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#include "TClonesArray.h"
33
34#include "TSQLFile.h"
35#include "TSQLClassInfo.h"
36#include "TSQLObjectData.h"
37#include "TBufferSQL2.h"
38
39#include "TSQLStatement.h"
40#include "TSQLServer.h"
41#include "TDataType.h"
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
143Long64_t sqlio::atol64(const char *value)
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
202void TSQLTableData::AddColumn(const char *name, Long64_t value)
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{
220 TObjString *v = new TObjString(value);
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 != 0)
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()) ? 0 : (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
450void TSQLStructure::ChangeValueOnly(const char *value)
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 != 0) && (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);
585 fChilds.Add(child);
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{
604 TSQLStructure *child = new TSQLStructure;
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{
646 TSQLStructure *child = new TSQLStructure;
647 child->SetObjectData(objdata);
648 Add(child);
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// searches for objects data
653
655{
656 TSQLStructure *child = GetChild(0);
657 if ((child != 0) && (child->GetType() == kSqlObjectData))
658 return (TSQLObjectData *)child->fPointer;
659 if (search && GetParent())
660 return GetParent()->GetObjectData(search);
661 return 0;
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 != 0)
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 0;
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(0), fNormStmt(0) {}
791
792 virtual ~TSqlCmdsBuffer()
793 {
794 fNormCmds.Delete();
795 fBlobCmds.Delete();
796 fFile->SQLDeleteStatement(fBlobStmt);
797 fFile->SQLDeleteStatement(fNormStmt);
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
809 TSQLFile *fFile;
810 TSQLClassInfo *fInfo;
811 TObjArray fNormCmds;
812 TObjArray fBlobCmds;
813 TSQLStatement *fBlobStmt;
814 TSQLStatement *fNormStmt;
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:
824 TSqlRegistry()
825 : TObject(), fFile(0), fKeyId(0), fLastObjId(-1), fCmds(0), fFirstObjId(0), fCurrentObjId(0), fCurrentObjClass(0),
826 fLastLongStrId(0), fPool(), fLongStrValues(), fRegValues(), fRegStmt(0)
827 {
828 }
829
830 TSQLFile *fFile;
831 Long64_t fKeyId;
832 Long64_t fLastObjId;
833 TObjArray *fCmds;
834 Long64_t fFirstObjId;
835
836 Long64_t fCurrentObjId;
837 TClass *fCurrentObjClass;
838
839 Int_t fLastLongStrId;
840
841 TMap fPool;
842 TObjArray fLongStrValues;
843 TObjArray fRegValues;
844
845 TSQLStatement *fRegStmt;
846
847 virtual ~TSqlRegistry()
848 {
849 fPool.DeleteValues();
850 fLongStrValues.Delete();
851 fRegValues.Delete();
852 fFile->SQLDeleteStatement(fRegStmt);
853 }
854
855 Long64_t GetNextObjId() { return ++fLastObjId; }
856
857 void AddSqlCmd(const char *query)
858 {
859 // add SQL command to the list
860 if (fCmds == 0)
861 fCmds = new TObjArray;
862 fCmds->Add(new TObjString(query));
863 }
864
865 TSqlCmdsBuffer *GetCmdsBuffer(TSQLClassInfo *sqlinfo)
866 {
867 if (sqlinfo == 0)
868 return 0;
869 TSqlCmdsBuffer *buf = (TSqlCmdsBuffer *)fPool.GetValue(sqlinfo);
870 if (buf == 0) {
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 == 0))
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 = 0;
895 while ((cmd = iter()) != 0) {
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
915 void ConvertPoolValues()
916 {
917 TSQLClassInfo *sqlinfo = 0;
918 TIter iter(&fPool);
919 while ((sqlinfo = (TSQLClassInfo *)iter()) != 0) {
920 TSqlCmdsBuffer *buf = (TSqlCmdsBuffer *)fPool.GetValue(sqlinfo);
921 if (buf == 0)
922 continue;
923 ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName());
924 // ensure that raw table will be created
925 if (buf->fBlobCmds.GetLast() >= 0)
926 fFile->CreateRawTable(sqlinfo);
927 ConvertSqlValues(buf->fBlobCmds, sqlinfo->GetRawTableName());
928 if (buf->fBlobStmt)
929 buf->fBlobStmt->Process();
930 if (buf->fNormStmt)
931 buf->fNormStmt->Process();
932 }
933
934 ConvertSqlValues(fLongStrValues, sqlio::StringsTable);
935 ConvertSqlValues(fRegValues, sqlio::ObjectsTable);
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 == 0) && 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 != 0) {
959 fRegStmt->NextIteration();
960 fRegStmt->SetLong64(0, fKeyId);
961 fRegStmt->SetLong64(1, objid);
962 fRegStmt->SetString(2, cl->GetName(), fFile->SQLSmallTextTypeLimit());
963 fRegStmt->SetInt(3, cl->GetClassVersion());
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)
980 fFile->VerifyLongStringTable();
981 Int_t strid = ++fLastLongStrId;
982 TString value = strvalue;
983 const char *valuequote = fFile->SQLValueQuote();
984 TSQLStructure::AddStrBrackets(value, valuequote);
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
994 Bool_t InsertToNormalTableOracle(TSQLTableData *columns, TSQLClassInfo *sqlinfo)
995 {
996 TSqlCmdsBuffer *buf = GetCmdsBuffer(sqlinfo);
997 if (buf == 0)
998 return kFALSE;
999
1000 TSQLStatement *stmt = buf->fNormStmt;
1001 if (stmt == 0) {
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 == 0)
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 == 0)
1033 value = "";
1034 stmt->SetString(ncol, value, sizelimit);
1035 }
1036
1037 return kTRUE;
1038 }
1039
1040 void InsertToNormalTable(TSQLTableData *columns, TSQLClassInfo *sqlinfo)
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);
1060 TSQLStructure::AddStrBrackets(value, valuequote);
1061 values += value;
1062 }
1063 }
1064
1065 TSqlCmdsBuffer *buf = GetCmdsBuffer(sqlinfo);
1066 if (buf != 0)
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:
1080 TSqlRawBuffer(TSqlRegistry *reg, TSQLClassInfo *sqlinfo)
1081 : TObject(), fFile(0), fInfo(0), fCmdBuf(0), fObjId(0), fRawId(0), fValueMask(), fValueQuote(0), fMaxStrSize(255)
1082 {
1083 fFile = reg->fFile;
1084 fInfo = sqlinfo;
1085 fCmdBuf = reg->GetCmdsBuffer(sqlinfo);
1086 fObjId = reg->fCurrentObjId;
1087 fValueQuote = fFile->SQLValueQuote();
1088 fValueMask.Form("%lld, %s, %s%s%s, %s", fObjId, "%d", fValueQuote, "%s", fValueQuote, "%s");
1089 fMaxStrSize = reg->fFile->SQLSmallTextTypeLimit();
1090 }
1091
1092 virtual ~TSqlRawBuffer()
1093 {
1094 // close blob statement for Oracle
1095 TSQLStatement *stmt = fCmdBuf->fBlobStmt;
1096 if ((stmt != 0) && fFile->IsOracle()) {
1097 stmt->Process();
1098 delete stmt;
1099 fCmdBuf->fBlobStmt = 0;
1100 }
1101 }
1102
1103 Bool_t IsAnyData() const { return fRawId > 0; }
1104
1105 void AddLine(const char *name, const char *value, const char *topname = 0, const char *ns = 0)
1106 {
1107 if (fCmdBuf == 0)
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 == 0) && fFile->SQLCanStatement();
1115
1116 if (maketmt) {
1117 // ensure that raw table is exists
1118 fFile->CreateRawTable(fInfo);
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 != 0) && (ns != 0)) {
1132 buf += topname;
1133 buf += ns;
1134 buf += name;
1135 fullname = buf.Data();
1136 }
1137
1138 TSQLStatement *stmt = fCmdBuf->fBlobStmt;
1139
1140 if (stmt != 0) {
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);
1149 TSQLStructure::AddStrBrackets(valuebuf, fValueQuote);
1150 TString cmd;
1151 cmd.Form(fValueMask.Data(), fRawId++, fullname, valuebuf.Data());
1152 fCmdBuf->AddValues(kFALSE, cmd.Data());
1153 }
1154 }
1155
1156 TSQLFile *fFile;
1157 TSQLClassInfo *fInfo;
1158 TSqlCmdsBuffer *fCmdBuf;
1159 Long64_t fObjId;
1160 Int_t fRawId;
1161 TString fValueMask;
1162 const char *fValueQuote;
1163 Int_t fMaxStrSize;
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 immidiately after TBufferSQL2 produces
1185/// this structure with object data
1186/// Should be only called for toplevel structure
1187
1189{
1190 if ((file == 0) || (cmds == 0))
1191 return kFALSE;
1192
1193 TSqlRegistry reg;
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 != 0)
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 == 0)
1250 return;
1251
1252 if (useblob) {
1253 for (Int_t n = 0; n <= fChilds.GetLast(); n++) {
1254 TSQLStructure *child = (TSQLStructure *)fChilds.At(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 != 0)
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 != 0)) {
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) ? 0 : 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++) {
1316 TSQLStructure *child = (TSQLStructure *)fChilds.At(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
1329Bool_t TSQLStructure::StoreObject(TSqlRegistry *reg, Long64_t objid, TClass *cl, Bool_t registerobj)
1330{
1331 if ((cl == 0) || (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++) {
1376 TSQLStructure *child = GetChild(n);
1377 child->PerformConversion(reg, &rawdata, 0 /*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 = 0;
1418 Version_t version = 0;
1419 if (!GetClassInfo(cl, version))
1420 return kFALSE;
1421 if (cl == 0)
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++) {
1437 TSQLStructure *child = (TSQLStructure *)fChilds.At(n);
1438 TStreamerElement *elem = child->GetElement();
1439
1440 if (elem == 0) {
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 == 0) || (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 == 0)
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) {
1564 TSQLStructure *child = GetChild(0);
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 }
1596 TSQLStructure *child = GetChild(0);
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++) {
1626 TSQLStructure *child = GetChild(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;
1649 TSQLStructure *child = GetChild(0);
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 shoud existing for element
1671 if (NumChilds() != 1) {
1672 Error("StoreElementInNormalForm", "Enexpected number %d for simple element %s", NumChilds(), elem->GetName());
1673 return kFALSE;
1674 }
1675
1676 TSQLStructure *child = GetChild(0);
1677 if (child->GetType() != kSqlValue)
1678 return kFALSE;
1679
1680 const char *value = child->GetValue();
1681 if (value == 0)
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 == 0)
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
1732Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry *reg, TSqlRawBuffer *blobs)
1733{
1734 TStreamerElement *elem = GetElement();
1735 if (elem == 0)
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 = 0;
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 == 0) || (s_info == 0) || (s_ver->GetType() != kSqlVersion))
1780 return kFALSE;
1781
1782 TClass *ver_cl = s_ver->GetVersionClass();
1783
1784 TClass *info_cl = 0;
1785 Version_t info_ver = 0;
1786 if (!s_info->GetClassInfo(info_cl, info_ver))
1787 return kFALSE;
1788
1789 if ((ver_cl == 0) || (info_cl == 0) || (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 != 0)
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 == 0)
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 = 0;
1849 if (!RecognizeTString(value))
1850 return kFALSE;
1851
1852 TSQLClassInfo *sqlinfo = reg->fFile->RequestSQLClassInfo(TString::Class());
1853 if (sqlinfo == 0)
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 = 0;
1873
1874 if ((NumChilds() == 0) || (NumChilds() > 3))
1875 return kFALSE;
1876
1877 TSQLStructure *len = 0, *lenbig = 0, *chars = 0;
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 == 0)
1884 len = curr;
1885 else
1886 return kFALSE;
1887 } else if (curr->fPointer == sqlio::Int) {
1888 if (lenbig == 0)
1889 lenbig = curr;
1890 else
1891 return kFALSE;
1892 } else if (curr->fPointer == sqlio::CharStar) {
1893 if (chars == 0)
1894 chars = curr;
1895 else
1896 return kFALSE;
1897 } else
1898 return kFALSE;
1899 }
1900
1901 if (len == 0)
1902 return kFALSE;
1903 if ((lenbig != 0) && (chars == 0))
1904 return kFALSE;
1905
1906 if (chars != 0)
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 == 0)
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() == 0)
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() != 0))
1976 return kColNormObject;
1977 else
1978 return kColNormObjectArray;
1979 }
1980
1987 if (elem->GetStreamer() != 0)
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() == 0)
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 == 0) || (data == 0))
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 == 0)
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 == 0) || !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 == 0)
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 == 0)
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 == 0) || !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) ? 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 == 0)
2306 return kFALSE;
2307
2308 TSQLObjectData *tobjdata = buf->SqlObjectData(objid, sqlinfo);
2309 if (tobjdata == 0)
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 != 0) && (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 == 0)
2340 return kFALSE;
2341
2342 TSQLObjectData *tstringdata = buf->SqlObjectData(objid, sqlinfo);
2343 if (tstringdata == 0)
2344 return kFALSE;
2345
2346 tstringdata->LocateColumn(sqlio::TStringValue);
2347
2348 const char *value = tstringdata->GetValue();
2349
2350 Int_t len = (value == 0) ? 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}
void Class()
Definition: Class.C:29
PyObject * fValue
PyObject * fType
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define BIT(n)
Definition: Rtypes.h:83
#define ClassImp(name)
Definition: Rtypes.h:365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
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:75
Version_t GetClassVersion() const
Definition: TClass.h:391
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:53
void DeleteValues()
Remove all (key,value) pairs from the map AND delete the values when they are allocated on the heap.
Definition: TMap.cxx:150
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
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:234
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:505
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:576
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:172
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:880
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:1428
Bool_t CreateRawTable(TSQLClassInfo *sqlinfo)
Create the raw table.
Definition: TSQLFile.cxx:2144
const char * SQLValueQuote() const
Definition: TSQLFile.h:143
Bool_t IsMySQL() const
checks, if MySQL database
Definition: TSQLFile.cxx:470
Bool_t IsOracle() const
checks, if Oracle database
Definition: TSQLFile.cxx:480
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:1442
void SQLDeleteStatement(TSQLStatement *stmt)
delete statement and decrease counter
Definition: TSQLFile.cxx:1462
Int_t SQLMaxIdentifierLength()
returns maximum allowed length of identifiers
Definition: TSQLFile.cxx:1600
Bool_t IsODBC() const
checks, if ODBC driver used for database connection
Definition: TSQLFile.cxx:490
Bool_t VerifyLongStringTable()
Checks that table for big strings is exists If not, will be created.
Definition: TSQLFile.cxx:2190
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:49
virtual Bool_t Process()=0
virtual Bool_t SetInt(Int_t, Int_t)
Definition: TSQLStatement.h:43
virtual Bool_t SetLong64(Int_t, Long64_t)
Definition: TSQLStatement.h:46
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:43
@ 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