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