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