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