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