Logo ROOT   6.14/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
15 This is hierarchical structure, which is created when data is written
16 by TBufferSQL2. It contains data all structural information such:
17 version of written class, data member types of that class, value for
18 each data member and so on.
19 Such structure in some sense similar to XML node and subnodes structure
20 Once it created, it converted to SQL statements, which are submitted
21 to 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 
43 namespace sqlio {
44 const Int_t Ids_NullPtr = 0; // used to identify NULL pointer in tables
45 const Int_t Ids_RootDir = 0; // dir:id, used for keys stored in root directory.
46 const Int_t Ids_TSQLFile = 0; // keyid for TSQLFile entry in keys list
47 const Int_t Ids_StreamerInfos = 1; // keyid used to store StreamerInfos in ROOT directory
48 const Int_t Ids_FirstKey = 10; // first key id, which is used in KeysTable (beside streamer info or something else)
49 const Int_t Ids_FirstObject = 1; // first object id, allowed in object tables
50 
51 const char *ObjectRef = "ObjectRef";
52 const char *ObjectRef_Arr = "ObjectRefArr";
53 const char *ObjectPtr = "ObjectPtr";
54 const char *ObjectInst = "ObjectInst";
55 const char *Version = "Version";
56 const char *TObjectUniqueId = "UniqueId";
57 const char *TObjectBits = "Bits";
58 const char *TObjectProcessId = "ProcessId";
59 const char *TStringValue = "StringValue";
60 const char *IndexSepar = "..";
61 const char *RawSuffix = ":rawdata";
62 const char *ParentSuffix = ":parent";
63 const char *ObjectSuffix = ":object";
64 const char *PointerSuffix = ":pointer";
65 const char *StrSuffix = ":str";
66 const char *LongStrPrefix = "#~#";
67 
68 const char *Array = "Array";
69 const char *Bool = "Bool_t";
70 const char *Char = "Char_t";
71 const char *Short = "Short_t";
72 const char *Int = "Int_t";
73 const char *Long = "Long_t";
74 const char *Long64 = "Long64_t";
75 const char *Float = "Float_t";
76 const char *Double = "Double_t";
77 const char *UChar = "UChar_t";
78 const char *UShort = "UShort_t";
79 const char *UInt = "UInt_t";
80 const char *ULong = "ULong_t";
81 const char *ULong64 = "ULong64_t";
82 const char *CharStar = "CharStar";
83 const char *True = "1";
84 const char *False = "0";
85 
86 // standard tables names
87 const char *KeysTable = "KeysTable";
88 const char *KeysTableIndex = "KeysTableIndex";
89 const char *ObjectsTable = "ObjectsTable";
90 const char *ObjectsTableIndex = "ObjectsTableIndex";
91 const char *IdsTable = "IdsTable";
92 const char *IdsTableIndex = "IdsTableIndex";
93 const char *StringsTable = "StringsTable";
94 const char *ConfigTable = "Configurations";
95 
96 // columns in Keys table
97 const char *KT_Name = "Name";
98 const char *KT_Title = "Title";
99 const char *KT_Datetime = "Datime";
100 const char *KT_Cycle = "Cycle";
101 const char *KT_Class = "Class";
102 
103 const char *DT_Create = "CreateDatime";
104 const char *DT_Modified = "ModifiedDatime";
105 const char *DT_UUID = "UUID";
106 
107 // columns in Objects table
108 const char *OT_Class = "Class";
109 const char *OT_Version = "Version";
110 
111 // columns in Identifiers Table
112 const char *IT_TableID = "TableId";
113 const char *IT_SubID = "SubId";
114 const char *IT_Type = "Type";
115 const char *IT_FullName = "FullName";
116 const char *IT_SQLName = "SQLName";
117 const char *IT_Info = "Info";
118 
119 // colummns in _streamer_ tables
120 const char *BT_Field = "Field";
121 const char *BT_Value = "Value";
122 
123 // colummns in string table
124 const char *ST_Value = "LongStringValue";
125 
126 // columns in config table
127 const char *CT_Field = "Field";
128 const char *CT_Value = "Value";
129 
130 // values in config table
131 const char *cfg_Version = "SQL_IO_version";
132 const char *cfg_UseSufixes = "UseNameSuffix";
133 const char *cfg_ArrayLimit = "ArraySizeLimit";
134 const char *cfg_TablesType = "TablesType";
135 const char *cfg_UseTransactions = "UseTransactions";
136 const char *cfg_UseIndexes = "UseIndexes";
137 const char *cfg_LockingMode = "LockingMode";
138 const char *cfg_ModifyCounter = "ModifyCounter";
139 };
140 
141 //________________________________________________________________________
142 
143 Long64_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 
168 TSQLColumnData::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 {
206  fColumns.Delete();
207  if (fColInfos != 0) {
208  fColInfos->Delete();
209  delete fColInfos;
210  }
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Add INT column to list of columns
215 
216 void 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)
226  fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), "INT"));
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Add normal column to list of columns
231 
232 void 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)
242  fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), sqltype));
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// produce suitable name for column, taking into account length limitation
247 
249 {
250  Int_t maxlen = fFile->SQLMaxIdentifierLength();
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 
288 Bool_t TSQLTableData::HasSQLName(const char *sqlname)
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) {
354  TSQLObjectData *objdata = (TSQLObjectData *)fPointer;
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 {
383  fType = kSqlObject;
384  fValue.Form("%lld", refid);
385  fPointer = cl;
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// set structure type as kSqlPointer
390 
392 {
393  fType = kSqlPointer;
394  fValue.Form("%lld", ptrid);
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// set structure type as kSqlVersion
399 
400 void TSQLStructure::SetVersion(const TClass *cl, Int_t version)
401 {
402  fType = kSqlVersion;
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 {
432  fType = kSqlElement;
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 
459 void TSQLStructure::SetValue(const char *value, const char *tname)
460 {
461  fType = kSqlValue;
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 
470 void 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 {
500  fType = kSqlArray;
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 {
534  return (fType == kSqlElement) || (fType == kSqlCustomElement) ? (TStreamerElement *)fPointer : 0;
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 
548 const char *TSQLStructure::GetValueType() const
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) {
575  TStreamerInfo *info = GetStreamerInfo();
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 
593 const 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 
612 void 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 
622 void 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  }
713  case kSqlCustomElement:
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) {
779  case TStreamerInfo::kChar: return sqlio::Char;
780  case TStreamerInfo::kShort: return sqlio::Short;
781  case TStreamerInfo::kInt: return sqlio::Int;
782  case TStreamerInfo::kLong: return sqlio::Long;
783  case TStreamerInfo::kFloat: return sqlio::Float;
785  case TStreamerInfo::kCounter: return sqlio::Int;
788  case TStreamerInfo::kUChar: return sqlio::UChar;
790  case TStreamerInfo::kUInt: return sqlio::UInt;
791  case TStreamerInfo::kULong: return sqlio::ULong;
792  case TStreamerInfo::kBits: return sqlio::UInt;
795  case TStreamerInfo::kBool: return sqlio::Bool;
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 
807 class TSqlCmdsBuffer : public TObject {
808 
809 public:
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 
841 class TSqlRegistry : public TObject {
842 
843 public:
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 
1097 class TSqlRawBuffer : public TObject {
1098 
1099 public:
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 
1236 void 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 
1268  TStreamerInfo *info = GetStreamerInfo();
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 
1349 Bool_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 
1752 Bool_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) {
1961  if (elem->InheritsFrom(TStreamerBase::Class()))
1962  return kColParent;
1963  else
1964  return kColObject;
1965  }
1966 
1967  if (typ == TStreamerInfo::kTNamed) {
1968  if (elem->InheritsFrom(TStreamerBase::Class()))
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)
1981  if (elem->InheritsFrom(TStreamerBase::Class()))
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 
2321 Bool_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 
2338  tobjdata->LocateColumn(sqlio::TObjectBits);
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 
2355 Bool_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 
2388 void 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 SetObjectData(TSQLObjectData *objdata)
set element to be used for object data
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
const char * GetValueType() const
return value type if structure is kSqlValue
TString fName
! name of the table column
Definition: TSQLStructure.h:44
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
const char * ConfigTable
static Int_t DefineElementColumnType(TStreamerElement *elem, TSQLFile *f)
defines which kind of column can be assigned for this element Possible cases kColSimple - basic data ...
An array of TObjects.
Definition: TObjArray.h:37
virtual Bool_t SetLong64(Int_t, Long64_t)
Definition: TSQLStatement.h:45
TSQLColumnData()
default constructor
Bool_t StoreTObject(TSqlRegistry *reg)
store data of TObject in special table workaround custom TObject streamer
const char * IdsTableIndex
TStreamerInfo * GetStreamerInfo() const
return TStreamerInfo* if type is kSqlStreamerInfo
long long Long64_t
Definition: RtypesCore.h:69
Long64_t FindMaxObjectId()
define maximum reference id, used for objects
static Bool_t IsNumericType(Int_t typ)
defines if value is numeric and not requires quotes when writing
void ShiftToNextValue()
shift to next column or next row in blob data
const char * GetValue() const
short Version_t
Definition: RtypesCore.h:61
const char * GetClassTableName() const
Definition: TSQLClassInfo.h:56
Version_t GetCustomClassVersion() const
return custom class version if strutures is kSqlCustomClass
Collectable string class.
Definition: TObjString.h:28
Equal to TDataType&#39;s kchar.
void AddValue(const char *value, const char *tname=0)
Add child structure as value.
const char * Int
const char Option_t
Definition: RtypesCore.h:62
Bool_t fNumeric
! for numeric quotes (double quotes) are not required
Definition: TSQLStructure.h:47
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
Bool_t GetClassInfo(TClass *&cl, Version_t &version)
provides class info if structure kSqlStreamerInfo or kSqlCustomClass
const char * cfg_UseTransactions
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
#define BIT(n)
Definition: Rtypes.h:78
Int_t GetType() const
static TString MakeArrayIndex(TStreamerElement *elem, Int_t n)
produce string with complete index like [1][2][0]
Int_t GetElementNumber() const
returns number of TStremerElement in TStreamerInfo
virtual Bool_t NextIteration()=0
const Int_t Ids_NullPtr
TMemberStreamer * GetStreamer() const
Return the local streamer object.
const char * CT_Value
Int_t GetNumColumns()
returns number of columns in provided set
void SQLDeleteStatement(TSQLStatement *stmt)
delete statement and decrease counter
Definition: TSQLFile.cxx:1469
const char * IndexSepar
TObjArray * fColInfos
! array with TSQLClassColumnInfo, used later for TSQLClassInfo
Definition: TSQLStructure.h:71
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
Int_t IsLongStringCode(Long64_t objid, const char *value)
Checks if this is long string code returns 0, if not or string id.
Definition: TSQLFile.cxx:2238
TClass * GetCustomClass() const
return element custom class if strutures is kSqlCustomClass
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
Contains information about tables specific to one class and version.
Definition: TSQLClassInfo.h:42
const char * IT_SQLName
const char * Long
Basic string class.
Definition: TString.h:131
void SetVersion(const TClass *cl, Int_t version=-100)
set structure type as kSqlVersion
const char * cfg_LockingMode
Int_t GetArrayLength() const
TSQLStructure * GetChild(Int_t n) const
return child structure of index n
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
const char * ObjectInst
bool Bool_t
Definition: RtypesCore.h:59
const char * IdsTable
const char * Char
const char * Version
void SetObjectRef(Long64_t refid, const TClass *cl)
set structure type as kSqlObject
virtual Bool_t SetString(Int_t, const char *, Int_t=256)
Definition: TSQLStatement.h:48
TSQLObjectData * SqlObjectData(Long64_t objid, TSQLClassInfo *sqlinfo)
Creates TSQLObjectData for specified object id and specified class.
void SetValue(const char *value, const char *tname=0)
set structure type as kSqlValue
const char * DT_Create
TString & Prepend(const char *cs)
Definition: TString.h:656
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
const char * UShort
Int_t GetArrayDim() const
void SetParent(TSQLStructure *p)
const char * UInt
const char * IT_Type
Bool_t CheckNormalClassPair(TSQLStructure *vers, TSQLStructure *info)
check if pair of two element corresponds to start of object, stored in normal form ...
Int_t GetArrayIndex() const
const char * ParentSuffix
const char * cfg_UseIndexes
const char * GetValue() const
returns value for different structure kinds has different sense For kSqlVersion it version...
TObjArray * TakeColInfos()
take ownership over colinfos
void SetStreamerInfo(const TStreamerInfo *info)
set structure type as kSqlStreamerInfo
TSQLObjectData is used in TBufferSQL2 class in reading procedure.
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
void Add(TSQLStructure *child)
Add child structure.
const char * StringsTable
Long64_t atol64(const char *value)
const char * TStringValue
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
const char * StrSuffix
const char * IT_FullName
Bool_t GetUseSuffixes() const
Definition: TSQLFile.h:186
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.
const char * True
void SetStreamerElement(const TStreamerElement *elem, Int_t number)
set structure type as kSqlElement
const char * ObjectsTableIndex
void Class()
Definition: Class.C:29
Int_t NumChilds() const
number of child structures
TString fValue
! value of the table column
Definition: TSQLStructure.h:46
Bool_t RecognizeTString(const char *&value)
prove that structure contains TString data
Int_t SQLSmallTextTypeLimit() const
Definition: TSQLFile.h:133
const char * KT_Datetime
void ChildArrayIndex(Int_t index, Int_t cnt=1)
set array index for last child element if (cnt<=1) return;
This is hierarchical structure, which is created when data is written by TBufferSQL2.
Definition: TSQLStructure.h:94
const void * fPointer
TString & Append(const char *cs)
Definition: TString.h:559
Bool_t StoreElementInNormalForm(TSqlRegistry *reg, TSQLTableData *columns)
tries to store element data in column
const char * KT_Cycle
virtual void Print(Option_t *option="") const
print content of complete structure
TSQLStatement * SQLStatement(const char *cmd, Int_t bufsize=1000)
Produces SQL statement for currently conected DB server.
Definition: TSQLFile.cxx:1449
Bool_t IsClassTableExist() const
Definition: TSQLClassInfo.h:63
TStreamerElement * GetElement() const
return TStremerElement* if type is kSqlElement
const char * cfg_TablesType
Bool_t TryConvertObjectArray(TSqlRegistry *reg, TSqlRawBuffer *blobs)
tries to write array of objects as list of object references in streamer table, while objects itself ...
const char * ST_Value
Long64_t Atoll() const
Return long long value of string.
Definition: TString.cxx:1922
TObject()
TObject constructor.
Definition: TObject.h:226
const char * GetSQLName() const
Definition: TSQLClassInfo.h:29
Bool_t SQLCanStatement()
Test if DB support statement and number of open statements is not exceeded.
Definition: TSQLFile.cxx:1435
Bool_t GetLongString(Long64_t objid, Int_t strid, TString &value)
Returns value of string, extracted from special table, where long strings are stored.
Definition: TSQLFile.cxx:2287
Int_t GetArrayLimit() const
Definition: TSQLFile.h:188
const char * KT_Title
const char * UChar
const char * Float
Bool_t StoreTString(TSqlRegistry *reg)
store data of TString in special table it is required when TString stored as pointer and reference to...
const Int_t Ids_TSQLFile
Int_t LocateElementColumn(TSQLFile *f, TBufferSQL2 *buf, TSQLObjectData *data)
find column in TSQLObjectData object, which correspond to current element
const char * OT_Class
virtual ~TSQLStructure()
destructor
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.
TObjArray fChilds
TSQLObjectData * GetObjectData(Bool_t search=false)
searches for objects data
static TString DefineElementColumnName(TStreamerElement *elem, TSQLFile *f, Int_t indx=0)
returns name of the column in class table for that element
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
const char * KeysTableIndex
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 AddColumn(const char *name, Long64_t value)
Add INT column to list of columns.
const char * KT_Class
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
TClass * GetClass() const
Access an SQL db via the TFile interface.
Definition: TSQLFile.h:30
const char * Array
void SetCustomClass(const TClass *cl, Version_t version)
set structure type as kSqlCustomClass
SVector< double, 2 > v
Definition: Dict.h:5
const char * IT_Info
const char * DT_Modified
PyObject * fValue
void ChangeValueOnly(const char *value)
change value of this structure used as "workaround" to keep object id in kSqlElement node ...
TString DefineSQLName(const char *fullname)
produce suitable name for column, taking into account length limitation
TSQLClassInfo * FindSQLClassInfo(const char *clname, Int_t version)
Return (if exists) TSQLClassInfo for specified class name and version.
Definition: TSQLFile.cxx:1785
Bool_t IsODBC() const
checks, if ODBC driver used for database connection
Definition: TSQLFile.cxx:491
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Int_t GetMaxIndex(Int_t i) const
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
const char * ObjectSuffix
Ssiz_t Length() const
Definition: TString.h:405
const char * ULong
const char * LongStrPrefix
void SetArray(Int_t sz=-1)
Set structure as array element.
Bool_t HasSQLName(const char *sqlname)
checks if columns list already has that sql name
const char * Double
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
void AddObjectData(TSQLObjectData *objdata)
add element with pointer to object data
const char * KeysTable
TSQLTableData(TSQLFile *f=0, TSQLClassInfo *info=0)
normal constructor
const char * OT_Version
const char * GetRawTableName() const
Definition: TSQLClassInfo.h:57
const char * TObjectUniqueId
const char * ObjectRef_Arr
Bool_t LocateColumn(const char *colname, Bool_t isblob=kFALSE)
locate column of that name in results
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
virtual ~TSQLColumnData()
TSQLColumnData destructor.
const char * cfg_Version
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...
const Bool_t kFALSE
Definition: RtypesCore.h:88
PyObject * fType
Bool_t IsNumeric(Int_t n)
identifies if column has numeric value
void SetCustomElement(TStreamerElement *elem)
set structure type as kSqlCustomElement
Bool_t PrepareForRawData()
prepare to read data from raw table
const char * TObjectBits
Converts data to SQL statements or read data from SQL tables.
Definition: TBufferSQL2.h:29
TClass * GetObjectClass() const
return object class if type kSqlObject
Version_t GetClassVersion() const
Definition: TClass.h:391
const Int_t Ids_FirstObject
Bool_t IsOracle() const
checks, if Oracle database
Definition: TSQLFile.cxx:481
Bool_t CreateRawTable(TSQLClassInfo *sqlinfo)
Create the raw table.
Definition: TSQLFile.cxx:2154
#define ClassImp(name)
Definition: Rtypes.h:359
void SetObjectPointer(Long64_t ptrid)
set structure type as kSqlPointer
void AddVersion(const TClass *cl, Int_t version=-100)
add child as version
const char * BT_Field
TClass * GetVersionClass() const
return class for version tag if type is kSqlVersion
static const char * GetSimpleTypeName(Int_t typ)
provides name for basic types used as suffix for column name or field suffix in raw table ...
void AddUnpack(const char *tname, const char *value)
add emulated data this used to place version or TObject raw data, read from normal tables ...
const char * SQLValueQuote() const
Definition: TSQLFile.h:143
TSQLClassInfo * GetInfo() const
const char * RawSuffix
const Int_t Ids_StreamerInfos
const char * TObjectProcessId
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
const char * DT_UUID
const char * GetColumn(Int_t n)
return column value
const char * ObjectPtr
static void AddStrBrackets(TString &s, const char *quote)
adds quotes around string value and replaces some special symbols
static constexpr double s
const char * KT_Name
const char * ULong64
const char * CT_Field
const char * cfg_ArrayLimit
const Int_t Ids_FirstKey
const char * SQLNameSeparator() const
Definition: TSQLFile.h:142
const char * CharStar
const char * Bool
Bool_t IsMySQL() const
checks, if MySQL database
Definition: TSQLFile.cxx:471
Mother of all ROOT objects.
Definition: TObject.h:37
TString fType
! type of the table column
Definition: TSQLStructure.h:45
Int_t GetClassVersion() const
const Int_t Ids_RootDir
void AddUnpackInt(const char *tname, Int_t value)
emulate integer value in raw data
Bool_t StoreClassInNormalForm(TSqlRegistry *reg)
produces data for complete class table where not possible, raw data for some elements are created ...
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 ...
Definition: file.py:1
Bool_t VerifyLongStringTable()
Checks that table for big strings is exists If not, will be created.
Definition: TSQLFile.cxx:2200
const char * PointerSuffix
const char * ObjectsTable
Long64_t DefineObjectId(Bool_t recursive=kTRUE)
defines current object id, to which this structure belong make life complicated, because some objects...
const char * BT_Value
virtual Bool_t Process()=0
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition: TMap.cxx:235
Bool_t StoreObjectInNormalForm(TSqlRegistry *reg)
this function verify object child elements and calls transformation to class table ...
void Add(TObject *obj)
Definition: TObjArray.h:73
Bool_t ConvertToTables(TSQLFile *f, Long64_t keyid, TObjArray *cmds)
Convert structure to sql statements This function is called immidiately after TBufferSQL2 produces th...
Int_t GetRepeatCounter() const
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
TSQLFile * fFile
!
Definition: TSQLStructure.h:68
virtual Bool_t SetInt(Int_t, Int_t)
Definition: TSQLStatement.h:42
Int_t SQLMaxIdentifierLength()
returns maximum allowed length of identifiers
Definition: TSQLFile.cxx:1608
void PrintLevel(Int_t level) const
print content of current structure
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t GetType() const
const char * ObjectRef
static constexpr double ns
const Int_t n
Definition: legend1.C:16
const char * SQLIdentifierQuote() const
Definition: TSQLFile.h:136
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:74
const char * Long64
TSQLStructure * GetParent() const
virtual const char * GetName() const
Return name of this collection.
const char * IT_TableID
const char * False
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1070
TObjArray fColumns
! collection of columns
Definition: TSQLStructure.h:70
const char * cfg_UseSufixes
const char * Data() const
Definition: TString.h:364
virtual ~TSQLTableData()
destructor
void SetArrayIndex(Int_t indx, Int_t cnt=1)
set array index for this structure
const char * Short
const char * IT_SubID
const char * cfg_ModifyCounter
void SetClassStreamer(const TClass *cl)
set structure type as kSqlClassStreamer