TSQLStructure.cxx

Go to the documentation of this file.
00001 // @(#)root/sql:$Id: TSQLStructure.cxx 35985 2010-10-01 10:24:07Z pcanal $
00002 // Author: Sergey Linev  20/11/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //________________________________________________________________________
00013 //
00014 //  This is hierarhical structure, which is created when data is written
00015 //  by TBufferSQL2. It contains data all structurual information such:
00016 //  version of written class, data memeber types of that class, value for
00017 //  each data memeber and so on.
00018 //  Such structure in some sense similar to XML node and subnodes structure
00019 //  Once it created, it converted to SQL statements, which are submitted
00020 //  to database server.
00021 //
00022 //________________________________________________________________________
00023 
00024 #include "TSQLStructure.h"
00025 
00026 #include "Riostream.h"
00027 #include "TMap.h"
00028 #include "TClass.h"
00029 #include "TStreamerInfo.h"
00030 #include "TStreamerElement.h"
00031 #include "TObjString.h"
00032 #include "TClonesArray.h"
00033 
00034 #include "TSQLFile.h"
00035 #include "TSQLClassInfo.h"
00036 #include "TSQLObjectData.h"
00037 #include "TBufferSQL2.h"
00038 
00039 #include "TSQLStatement.h"
00040 #include "TSQLServer.h"
00041 #include "TDataType.h"
00042 
00043 namespace sqlio {
00044    const Int_t Ids_NullPtr       = 0; // used to identify NULL pointer in tables
00045    const Int_t Ids_RootDir       = 0; // dir:id, used for keys stored in root directory.
00046    const Int_t Ids_TSQLFile      = 0; // keyid for TSQLFile entry in keys list
00047    const Int_t Ids_StreamerInfos = 1; // keyid used to store StreamerInfos in ROOT directory
00048    const Int_t Ids_FirstKey      =10; // first key id, which is used in KeysTable (beside streamer info or something else)
00049    const Int_t Ids_FirstObject   = 1; // first object id, allowed in object tables
00050 
00051    const char* ObjectRef     = "ObjectRef";
00052    const char* ObjectRef_Arr = "ObjectRefArr";
00053    const char* ObjectPtr     = "ObjectPtr";
00054    const char* ObjectInst    = "ObjectInst";
00055    const char* Version       = "Version";
00056    const char* TObjectUniqueId = "UniqueId";
00057    const char* TObjectBits = "Bits";
00058    const char* TObjectProcessId = "ProcessId";
00059    const char* TStringValue= "StringValue";
00060    const char* IndexSepar  = "..";
00061    const char* RawSuffix = ":rawdata";
00062    const char* ParentSuffix = ":parent";
00063    const char* ObjectSuffix = ":object";
00064    const char* PointerSuffix = ":pointer";
00065    const char* StrSuffix     = ":str";
00066    const char* LongStrPrefix = "#~#";
00067 
00068    const char* Array       = "Array";
00069    const char* Bool        = "Bool_t";
00070    const char* Char        = "Char_t";
00071    const char* Short       = "Short_t";
00072    const char* Int         = "Int_t";
00073    const char* Long        = "Long_t";
00074    const char* Long64      = "Long64_t";
00075    const char* Float       = "Float_t";
00076    const char* Double      = "Double_t";
00077    const char* UChar       = "UChar_t";
00078    const char* UShort      = "UShort_t";
00079    const char* UInt        = "UInt_t";
00080    const char* ULong       = "ULong_t";
00081    const char* ULong64     = "ULong64_t";
00082    const char* CharStar    = "CharStar";
00083    const char* True        = "1";
00084    const char* False       = "0";
00085 
00086    // standard tables names
00087    const char* KeysTable      = "KeysTable";
00088    const char* KeysTableIndex = "KeysTableIndex";
00089    const char* ObjectsTable   = "ObjectsTable";
00090    const char* ObjectsTableIndex = "ObjectsTableIndex";
00091    const char* IdsTable = "IdsTable";
00092    const char* IdsTableIndex = "IdsTableIndex";
00093    const char* StringsTable   = "StringsTable";
00094    const char* ConfigTable    = "Configurations";
00095 
00096    // colummns in Keys table
00097    const char* KT_Name      = "Name";
00098    const char* KT_Title     = "Title";
00099    const char* KT_Datetime  = "Datime";
00100    const char* KT_Cycle     = "Cycle";
00101    const char* KT_Class     = "Class";
00102 
00103    const char* DT_Create    = "CreateDatime";
00104    const char* DT_Modified  = "ModifiedDatime";
00105    const char* DT_UUID      = "UUID";
00106 
00107    // colummns in Objects table
00108    const char* OT_Class     = "Class";
00109    const char* OT_Version   = "Version";
00110 
00111    // columns in Identifiers Table
00112    const char* IT_TableID   = "TableId";
00113    const char* IT_SubID     = "SubId";
00114    const char* IT_Type      = "Type";
00115    const char* IT_FullName  = "FullName";
00116    const char* IT_SQLName   = "SQLName";
00117    const char* IT_Info      = "Info";
00118 
00119    // colummns in _streamer_ tables
00120    const char* BT_Field     = "Field";
00121    const char* BT_Value     = "Value";
00122 
00123    // colummns in string table
00124    const char* ST_Value     = "LongStringValue";
00125 
00126    // columns in config table
00127    const char* CT_Field     = "Field";
00128    const char* CT_Value     = "Value";
00129 
00130    // values in config table
00131    const char* cfg_Version  = "SQL_IO_version";
00132    const char* cfg_UseSufixes = "UseNameSuffix";
00133    const char* cfg_ArrayLimit = "ArraySizeLimit";
00134    const char* cfg_TablesType = "TablesType";
00135    const char* cfg_UseTransactions = "UseTransactions";
00136    const char* cfg_UseIndexes = "UseIndexes";
00137    const char* cfg_LockingMode = "LockingMode";
00138    const char* cfg_ModifyCounter = "ModifyCounter";
00139 };
00140 
00141 //________________________________________________________________________
00142 
00143 #ifdef R__VISUAL_CPLUSPLUS
00144 #define FLong64    "%I64d"
00145 #define FULong64   "%I64u"
00146 #else
00147 #define FLong64    "%lld"
00148 #define FULong64   "%llu"
00149 #endif
00150 
00151 Long64_t sqlio::atol64(const char* value)
00152 {
00153    if ((value==0) || (*value==0)) return 0;
00154    Long64_t res = 0;
00155    sscanf(value, FLong64, &res);
00156    return res;
00157 }
00158 
00159 
00160 ClassImp(TSQLColumnData)
00161 
00162 //______________________________________________________________________________
00163    TSQLColumnData::TSQLColumnData() :
00164       TObject(),
00165       fName(),
00166       fType(),
00167       fValue(),
00168       fNumeric(kFALSE)
00169 {
00170    // default constructor
00171 }
00172 
00173 //________________________________________________________________________
00174 TSQLColumnData::TSQLColumnData(const char* name,
00175                                const char* sqltype,
00176                                const char* value,
00177                                Bool_t numeric) :
00178    TObject(),
00179    fName(name),
00180    fType(sqltype),
00181    fValue(value),
00182    fNumeric(numeric)
00183 {
00184    // normal constructor of TSQLColumnData class
00185    // specifies name, type and value for one column
00186 }
00187 
00188 //________________________________________________________________________
00189 TSQLColumnData::TSQLColumnData(const char* name, Long64_t value) :
00190    TObject(),
00191    fName(name),
00192    fType("INT"),
00193    fValue(),
00194    fNumeric(kTRUE)
00195 {
00196    // constructs TSQLColumnData object for integer column
00197 
00198    fValue.Form("%lld",value);
00199 }
00200 
00201 //________________________________________________________________________
00202 TSQLColumnData::~TSQLColumnData()
00203 {
00204    // TSQLColumnData destructor
00205 }
00206 
00207 
00208 ClassImp(TSQLTableData);
00209 
00210 //________________________________________________________________________
00211 TSQLTableData::TSQLTableData(TSQLFile* f, TSQLClassInfo* info) : 
00212    TObject(),
00213    fFile(f),
00214    fInfo(info),
00215    fColumns(),
00216    fColInfos(0)
00217 {
00218    // normal constructor
00219    
00220    if (!info->IsClassTableExist()) 
00221       fColInfos = new TObjArray;
00222 }
00223 
00224 //________________________________________________________________________
00225 TSQLTableData::~TSQLTableData()
00226 {
00227    // destructor
00228    
00229    fColumns.Delete();
00230    if (fColInfos!=0) {
00231       fColInfos->Delete();
00232       delete fColInfos;  
00233    }
00234 }
00235 
00236 //________________________________________________________________________
00237 void TSQLTableData::AddColumn(const char* name, Long64_t value)
00238 {
00239    // Add INT column to list of columns
00240 
00241    TObjString* v = new TObjString(Form("%lld",value));
00242    v->SetBit(BIT(20), kTRUE);
00243    fColumns.Add(v);
00244 
00245 //   TSQLColumnData* col = new TSQLColumnData(name, value);
00246 //   fColumns.Add(col);
00247    
00248    if (fColInfos!=0)
00249      fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), "INT"));
00250 }
00251 
00252 //________________________________________________________________________
00253 void TSQLTableData::AddColumn(const char* name, 
00254                               const char* sqltype, 
00255                               const char* value, 
00256                               Bool_t numeric)
00257 {
00258    // Add nomral column to list of columns
00259 
00260    TObjString* v = new TObjString(value);
00261    v->SetBit(BIT(20), numeric);
00262    fColumns.Add(v);
00263    
00264 //   TSQLColumnData* col = new TSQLColumnData(name, sqltype, value, numeric);
00265 //   fColumns.Add(col);
00266 
00267    if (fColInfos!=0)
00268      fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), sqltype));
00269 }
00270 
00271 //________________________________________________________________________
00272 TString TSQLTableData::DefineSQLName(const char* fullname)
00273 {
00274    // produce suitable name for column, taking into account length limitation
00275    
00276    Int_t maxlen = fFile->SQLMaxIdentifierLength();
00277    
00278    Int_t len = strlen(fullname);
00279    
00280    if ((len<=maxlen) && !HasSQLName(fullname)) return TString(fullname);
00281    
00282    Int_t cnt = -1;
00283    TString res, scnt;
00284    
00285    do {
00286       
00287       scnt.Form("%d",cnt);
00288       Int_t numlen = cnt<0 ? 0 : scnt.Length();
00289       
00290       res = fullname;
00291       
00292       if (len + numlen > maxlen) 
00293          res.Resize(maxlen - numlen);
00294       
00295       if (cnt>=0) res+=scnt;
00296       
00297       if (!HasSQLName(res.Data())) return res;
00298       
00299       cnt++;
00300       
00301    } while (cnt<10000);
00302    
00303    Error("DefineSQLName","Cannot find reasonable column name for field %s",fullname);
00304    
00305    return TString(fullname);
00306 }
00307 
00308 //________________________________________________________________________
00309 Bool_t TSQLTableData::HasSQLName(const char* sqlname)
00310 {
00311    // checks if columns list already has that sql name
00312    
00313    TIter next(fColInfos);
00314 
00315    TSQLClassColumnInfo* col = 0;
00316    
00317    while ((col = (TSQLClassColumnInfo*) next()) != 0) {
00318       const char* colname = col->GetSQLName();
00319       if (strcmp(colname, sqlname)==0) return kTRUE;
00320    }
00321    
00322    return kFALSE;
00323 
00324 }
00325 
00326 //________________________________________________________________________
00327 Int_t TSQLTableData::GetNumColumns()
00328 {
00329    // returns number of columns in provided set
00330    
00331    return fColumns.GetLast() +1;
00332 }
00333 
00334 //________________________________________________________________________
00335 const char* TSQLTableData::GetColumn(Int_t n)
00336 {
00337    // returm column value
00338    return fColumns[n]->GetName();
00339 }
00340 
00341 //________________________________________________________________________
00342 Bool_t TSQLTableData::IsNumeric(Int_t n)
00343 {
00344    // identifies if column has numeric value
00345    
00346    return fColumns[n]->TestBit(BIT(20));
00347 }
00348 
00349 //________________________________________________________________________
00350 TObjArray* TSQLTableData::TakeColInfos() 
00351 { 
00352    // take ownership over colinfos
00353    
00354    TObjArray* res = fColInfos; 
00355    fColInfos = 0; 
00356    return res; 
00357 }
00358 
00359 //________________________________________________________________________
00360 
00361 ClassImp(TSQLStructure);
00362 
00363 TSQLStructure::TSQLStructure() :
00364    TObject(),
00365    fParent(0),
00366    fType(0),
00367    fPointer(0),
00368    fValue(),
00369    fArrayIndex(-1),
00370    fRepeatCnt(0),
00371    fChilds()
00372 {
00373    // default constructor
00374 }
00375 
00376 //________________________________________________________________________
00377 TSQLStructure::~TSQLStructure()
00378 {
00379    // destructor
00380 
00381    fChilds.Delete();
00382    if (GetType()==kSqlObjectData) {
00383       TSQLObjectData* objdata = (TSQLObjectData*) fPointer;
00384       delete objdata;
00385    } else
00386    if (GetType()==kSqlCustomElement) {
00387       TStreamerElement* elem = (TStreamerElement*) fPointer;
00388       delete elem;
00389    }
00390 }
00391 
00392 //________________________________________________________________________
00393 Int_t TSQLStructure::NumChilds() const
00394 {
00395    // number of child structures
00396 
00397    return fChilds.GetLast()+1;
00398 }
00399 
00400 //________________________________________________________________________
00401 TSQLStructure* TSQLStructure::GetChild(Int_t n) const
00402 {
00403    // return child structure of index n
00404 
00405    return (n<0) || (n>fChilds.GetLast()) ? 0 : (TSQLStructure*) fChilds[n];
00406 }
00407 
00408 //________________________________________________________________________
00409 void TSQLStructure::SetObjectRef(Long64_t refid, const TClass* cl)
00410 {
00411    // set structure type as kSqlObject
00412 
00413    fType = kSqlObject;
00414    fValue.Form("%lld",refid);
00415    fPointer = cl;
00416 }
00417 
00418 //________________________________________________________________________
00419 void TSQLStructure::SetObjectPointer(Long64_t ptrid)
00420 {
00421    // set structure type as kSqlPointer
00422 
00423    fType = kSqlPointer;
00424    fValue.Form("%lld",ptrid);
00425 }
00426 
00427 //________________________________________________________________________
00428 void TSQLStructure::SetVersion(const TClass* cl, Int_t version)
00429 {
00430    // set structure type as kSqlVersion
00431 
00432    fType = kSqlVersion;
00433    fPointer = cl;
00434    if (version<0) version = cl->GetClassVersion();
00435    fValue.Form("%d",version);
00436 }
00437 
00438 //________________________________________________________________________
00439 void TSQLStructure::SetClassStreamer(const TClass* cl)
00440 {
00441    // set structure type as kSqlClassStreamer
00442 
00443    fType = kSqlClassStreamer;
00444    fPointer = cl;
00445 }
00446 
00447 //________________________________________________________________________
00448 void TSQLStructure::SetStreamerInfo(const TStreamerInfo* info)
00449 {
00450    // set structure type as kSqlStreamerInfo
00451 
00452    fType = kSqlStreamerInfo;
00453    fPointer = info;
00454 }
00455 
00456 //________________________________________________________________________
00457 void TSQLStructure::SetStreamerElement(const TStreamerElement* elem, Int_t number)
00458 {
00459    // set structure type as kSqlElement
00460 
00461    fType = kSqlElement;
00462    fPointer = elem;
00463    fArrayIndex = number;
00464 }
00465 
00466 //________________________________________________________________________
00467 void TSQLStructure::SetCustomClass(const TClass* cl, Version_t version)
00468 {
00469    // set structure type as kSqlCustomClass
00470    
00471    fType = kSqlCustomClass;
00472    fPointer = (void*) cl;
00473    fArrayIndex = version;
00474 }
00475 
00476 //________________________________________________________________________
00477 void TSQLStructure::SetCustomElement(TStreamerElement* elem)
00478 {
00479    // set structure type as kSqlCustomElement
00480    
00481    fType = kSqlCustomElement;
00482    fPointer = elem;
00483 }
00484 
00485 //________________________________________________________________________
00486 void TSQLStructure::SetValue(const char* value, const char* tname)
00487 {
00488    // set structure type as kSqlValue
00489 
00490    fType = kSqlValue;
00491    fValue = value;
00492    fPointer = tname;
00493 }
00494 
00495 //________________________________________________________________________
00496 void TSQLStructure::ChangeValueOnly(const char* value)
00497 {
00498    // change value of this structure
00499    // used as "workaround" to keep object id in kSqlElement node
00500 
00501    fValue = value;
00502 }
00503 
00504 //________________________________________________________________________
00505 void TSQLStructure::SetArrayIndex(Int_t indx, Int_t cnt)
00506 {
00507    // set array index for this structure
00508 
00509    fArrayIndex = indx;
00510    fRepeatCnt = cnt;
00511 }
00512 
00513 //________________________________________________________________________
00514 void TSQLStructure::ChildArrayIndex(Int_t index, Int_t cnt)
00515 {
00516    // set array index for last child element
00517    //   if (cnt<=1) return;
00518    TSQLStructure* last = (TSQLStructure*) fChilds.Last();
00519    if ((last!=0) && (last->GetType()==kSqlValue))
00520       last->SetArrayIndex(index, cnt);
00521 }
00522 
00523 //________________________________________________________________________
00524 void TSQLStructure::SetArray(Int_t sz)
00525 {
00526    // Set structure as array element
00527 
00528    fType = kSqlArray;
00529    if (sz>=0) fValue.Form("%d",sz);
00530 }
00531 
00532 //________________________________________________________________________
00533 TClass* TSQLStructure::GetObjectClass() const
00534 {
00535    // return object class if type kSqlObject
00536 
00537    return (fType==kSqlObject) ? (TClass*) fPointer : 0;
00538 }
00539 
00540 //________________________________________________________________________
00541 TClass* TSQLStructure::GetVersionClass() const
00542 {
00543    // return class for version tag if type is kSqlVersion
00544 
00545    return (fType==kSqlVersion) ? (TClass*) fPointer : 0;
00546 }
00547 
00548 //________________________________________________________________________
00549 TStreamerInfo*  TSQLStructure::GetStreamerInfo() const
00550 {
00551    // return TStreamerInfo* if type is kSqlStreamerInfo
00552 
00553    return (fType==kSqlStreamerInfo) ? (TStreamerInfo*) fPointer : 0;
00554 }
00555 
00556 //________________________________________________________________________
00557 TStreamerElement* TSQLStructure::GetElement() const
00558 {
00559    // return TStremerElement* if type is kSqlElement
00560 
00561    return (fType==kSqlElement) || (fType==kSqlCustomElement) ? (TStreamerElement*) fPointer : 0;
00562 }
00563 
00564 //________________________________________________________________________
00565 Int_t TSQLStructure::GetElementNumber() const
00566 {
00567    // returns number of TStremerElement in TStreamerInfo
00568 
00569    return (fType==kSqlElement) ? fArrayIndex : 0;
00570 }
00571 
00572 //________________________________________________________________________
00573 const char* TSQLStructure::GetValueType() const
00574 {
00575    // return value type if structure is kSqlValue
00576 
00577    return (fType==kSqlValue) ? (const char*) fPointer : 0;
00578 }
00579 
00580 //________________________________________________________________________
00581 TClass* TSQLStructure::GetCustomClass() const
00582 {
00583    // return element custom class if strutures is kSqlCustomClass
00584    
00585    return (fType==kSqlCustomClass) ? (TClass*) fPointer : 0;
00586 }
00587 
00588 //________________________________________________________________________
00589 Version_t TSQLStructure::GetCustomClassVersion() const
00590 {
00591    // return custom class version if strutures is kSqlCustomClass
00592    
00593    return (fType==kSqlCustomClass) ? fArrayIndex : 0;
00594 }
00595 
00596 //________________________________________________________________________
00597 Bool_t TSQLStructure::GetClassInfo(TClass* &cl, Version_t &version)
00598 {
00599    // provides class info if structure kSqlStreamerInfo or kSqlCustomClass
00600    
00601    if (GetType()==kSqlStreamerInfo) {
00602       TStreamerInfo* info = GetStreamerInfo();
00603       if (info==0) return kFALSE;
00604       cl = info->GetClass();
00605       version = info->GetClassVersion();
00606    } else
00607    if (GetType()==kSqlCustomClass) {
00608       cl = GetCustomClass();
00609       version = GetCustomClassVersion();
00610    } else
00611       return kFALSE;
00612    return kTRUE;
00613 }
00614 
00615 //________________________________________________________________________
00616 const char* TSQLStructure::GetValue() const
00617 {
00618    // returns value
00619    // for different structure kinds has different sense
00620    // For kSqlVersion it version, for kSqlReference it is object id and so on
00621 
00622    return fValue.Data();
00623 }
00624 
00625 //________________________________________________________________________
00626 void TSQLStructure::Add(TSQLStructure* child)
00627 {
00628    // Add child strucure
00629 
00630    if (child!=0) {
00631       child->SetParent(this);
00632       fChilds.Add(child);
00633    }
00634 }
00635 
00636 //________________________________________________________________________
00637 void TSQLStructure::AddVersion(const TClass* cl, Int_t version)
00638 {
00639    // add child as version
00640 
00641    TSQLStructure* ver = new TSQLStructure;
00642    ver->SetVersion(cl, version);
00643    Add(ver);
00644 }
00645 
00646 //________________________________________________________________________
00647 void TSQLStructure::AddValue(const char* value, const char* tname)
00648 {
00649    // Add child structure as value
00650 
00651    TSQLStructure* child = new TSQLStructure;
00652    child->SetValue(value, tname);
00653    Add(child);
00654 }
00655 
00656 //________________________________________________________________________
00657 Long64_t TSQLStructure::DefineObjectId(Bool_t recursive)
00658 {
00659    // defines current object id, to which this structure belong
00660    // make life complicated, because some objects do not get id
00661    // automatically in TBufferSQL, but afterwards
00662 
00663    TSQLStructure* curr = this;
00664    while (curr!=0) {
00665       if ((curr->GetType()==kSqlObject) ||
00666           (curr->GetType()==kSqlPointer) || 
00667          // workaround to store object id in element structure
00668           (curr->GetType()==kSqlElement) ||
00669           (curr->GetType()==kSqlCustomElement) ||
00670           (curr->GetType()==kSqlCustomClass) ||
00671           (curr->GetType()==kSqlStreamerInfo)) {
00672          const char* value = curr->GetValue();
00673          if ((value!=0) && (strlen(value)>0))
00674             return sqlio::atol64(value);
00675       }
00676 
00677       curr = recursive ? curr->GetParent() : 0;
00678    }
00679    return -1;
00680 }
00681 
00682 //________________________________________________________________________
00683 void TSQLStructure::SetObjectData(TSQLObjectData* objdata)
00684 {
00685    // set element to be used for object data
00686 
00687    fType = kSqlObjectData;
00688    fPointer = objdata;
00689 }
00690 
00691 //________________________________________________________________________
00692 void TSQLStructure::AddObjectData(TSQLObjectData* objdata)
00693 {
00694    // add element with pointer to object data
00695 
00696    TSQLStructure* child = new TSQLStructure;
00697    child->SetObjectData(objdata);
00698    Add(child);
00699 }
00700 
00701 //________________________________________________________________________
00702 TSQLObjectData* TSQLStructure::GetObjectData(Bool_t search)
00703 {
00704    // searchs for objects data
00705 
00706    TSQLStructure* child = GetChild(0);
00707    if ((child!=0) && (child->GetType()==kSqlObjectData))
00708       return (TSQLObjectData*) child->fPointer;
00709    if (search && (GetParent()!=0))
00710       return GetParent()->GetObjectData(search);
00711    return 0;
00712 }
00713 
00714 //________________________________________________________________________
00715 void TSQLStructure::Print(Option_t*) const
00716 {
00717    // print content of complete structure
00718 
00719    PrintLevel(0);
00720 }
00721 
00722 //________________________________________________________________________
00723 void TSQLStructure::PrintLevel(Int_t level) const
00724 {
00725    // print content of current structure
00726 
00727    for(Int_t n=0;n<level;n++) cout << " ";
00728    switch (fType) {
00729    case 0: cout << "Undefined type"; break;
00730    case kSqlObject: cout << "Object ref = " << fValue; break;
00731    case kSqlPointer: cout << "Pointer ptr = " << fValue; break;
00732    case kSqlVersion: {
00733       const TClass* cl = (const TClass*) fPointer;
00734       cout << "Version cl = " << cl->GetName() << " ver = " << cl->GetClassVersion();
00735       break;
00736    }
00737    case kSqlStreamerInfo: {
00738       const TStreamerInfo* info = (const TStreamerInfo*) fPointer;
00739       cout << "Class: " << info->GetName();
00740       break;
00741    }
00742    case kSqlCustomElement:
00743    case kSqlElement: {
00744       const TStreamerElement* elem = (const TStreamerElement*) fPointer;
00745       cout << "Member: " << elem->GetName();
00746       break;
00747    }
00748    case kSqlValue: {
00749       cout << "Value: " << fValue;
00750       if (fRepeatCnt>1) cout << "  cnt:" << fRepeatCnt;
00751       if (fPointer!=0) cout << "  type = " << (const char*)fPointer;
00752       break;
00753    }
00754    case kSqlArray: {
00755       cout << "Array ";
00756       if (fValue.Length()>0) cout << "  sz = " << fValue;
00757       break;
00758    }
00759    case kSqlCustomClass: {
00760       TClass* cl = (TClass*) fPointer;
00761       cout << "CustomClass: " << cl->GetName() << "  ver = " << fValue;
00762       break;
00763    }
00764    default:
00765       cout << "Unknown type";
00766    }
00767    cout << endl;
00768 
00769    for(Int_t n=0;n<NumChilds();n++)
00770       GetChild(n)->PrintLevel(level+2);
00771 }
00772 
00773 //________________________________________________________________________
00774 Bool_t TSQLStructure::IsNumericType(Int_t typ)
00775 {
00776    // defines if value is numeric and not requires quotes when writing
00777 
00778    switch(typ) {
00779    case TStreamerInfo::kShort   : return kTRUE;
00780    case TStreamerInfo::kInt     : return kTRUE;
00781    case TStreamerInfo::kLong    : return kTRUE;
00782    case TStreamerInfo::kFloat   : return kTRUE;
00783    case TStreamerInfo::kFloat16 : return kTRUE;
00784    case TStreamerInfo::kCounter : return kTRUE;
00785    case TStreamerInfo::kDouble  : return kTRUE;
00786    case TStreamerInfo::kDouble32: return kTRUE;
00787    case TStreamerInfo::kUChar   : return kTRUE;
00788    case TStreamerInfo::kUShort  : return kTRUE;
00789    case TStreamerInfo::kUInt    : return kTRUE;
00790    case TStreamerInfo::kULong   : return kTRUE;
00791    case TStreamerInfo::kBits    : return kTRUE;
00792    case TStreamerInfo::kLong64  : return kTRUE;
00793    case TStreamerInfo::kULong64 : return kTRUE;
00794    case TStreamerInfo::kBool    : return kTRUE;
00795    }
00796    return kFALSE;
00797 }
00798 
00799 //________________________________________________________________________
00800 const char* TSQLStructure::GetSimpleTypeName(Int_t typ)
00801 {
00802    // provides name for basic types
00803    // used as suffix for column name or field suffix in raw table
00804 
00805    switch(typ) {
00806    case TStreamerInfo::kChar    : return sqlio::Char;
00807    case TStreamerInfo::kShort   : return sqlio::Short;
00808    case TStreamerInfo::kInt     : return sqlio::Int;
00809    case TStreamerInfo::kLong    : return sqlio::Long;
00810    case TStreamerInfo::kFloat   : return sqlio::Float;
00811    case TStreamerInfo::kFloat16 : return sqlio::Float;
00812    case TStreamerInfo::kCounter : return sqlio::Int;
00813    case TStreamerInfo::kDouble  : return sqlio::Double;
00814    case TStreamerInfo::kDouble32: return sqlio::Double;
00815    case TStreamerInfo::kUChar   : return sqlio::UChar;
00816    case TStreamerInfo::kUShort  : return sqlio::UShort;
00817    case TStreamerInfo::kUInt    : return sqlio::UInt;
00818    case TStreamerInfo::kULong   : return sqlio::ULong;
00819    case TStreamerInfo::kBits    : return sqlio::UInt;
00820    case TStreamerInfo::kLong64  : return sqlio::Long64;
00821    case TStreamerInfo::kULong64 : return sqlio::ULong64;
00822    case TStreamerInfo::kBool    : return sqlio::Bool;
00823    }
00824 
00825    return 0;
00826 }
00827 
00828 //___________________________________________________________
00829 
00830 // TSqlCmdsBuffer used as buffer for data, which are correspond to
00831 // particular class, defined by TSQLClassInfo instance
00832 // Support both TSQLStatement and Query modes
00833 
00834 class TSqlCmdsBuffer : public TObject {
00835 
00836 public:
00837    TSqlCmdsBuffer(TSQLFile* f, TSQLClassInfo* info) :
00838       TObject(),
00839       fFile(f),
00840       fInfo(info),
00841       fBlobStmt(0),
00842       fNormStmt(0)
00843    {
00844    }
00845 
00846    virtual ~TSqlCmdsBuffer()
00847    {
00848       fNormCmds.Delete();
00849       fBlobCmds.Delete();
00850       fFile->SQLDeleteStatement(fBlobStmt);
00851       fFile->SQLDeleteStatement(fNormStmt);
00852    }
00853 
00854    void AddValues(Bool_t isnorm, const char* values)
00855    {
00856       TObjString* str = new TObjString(values);
00857       if (isnorm) fNormCmds.Add(str);
00858       else fBlobCmds.Add(str);
00859    }
00860 
00861    TSQLFile* fFile;
00862    TSQLClassInfo* fInfo;
00863    TObjArray fNormCmds;
00864    TObjArray fBlobCmds;
00865    TSQLStatement* fBlobStmt;
00866    TSQLStatement* fNormStmt;
00867 };
00868 
00869 //________________________________________________________________________
00870 // TSqlRegistry keeps data, used when object data transformed to sql query or
00871 // statements 
00872 
00873 class TSqlRegistry : public TObject {
00874 
00875 public:
00876    TSqlRegistry() :
00877       TObject(),
00878       f(0),
00879       fKeyId(0),
00880       fLastObjId(-1),
00881       fCmds(0),
00882       fFirstObjId(0),
00883       fCurrentObjId(0),
00884       fCurrentObjClass(0),
00885       fLastLongStrId(0),
00886       fPool(),
00887       fLongStrValues(),
00888       fRegValues(),
00889       fRegStmt(0)
00890    {
00891    }
00892 
00893    TSQLFile*  f;
00894    Long64_t   fKeyId;
00895    Long64_t   fLastObjId;
00896    TObjArray* fCmds;
00897    Long64_t   fFirstObjId;
00898 
00899    Long64_t   fCurrentObjId;
00900    TClass*    fCurrentObjClass;
00901 
00902    Int_t      fLastLongStrId;
00903 
00904    TMap       fPool;
00905    TObjArray  fLongStrValues;
00906    TObjArray  fRegValues;
00907    
00908    TSQLStatement* fRegStmt;
00909 
00910 
00911    virtual ~TSqlRegistry()
00912    {
00913       fPool.DeleteValues();
00914       fLongStrValues.Delete();
00915       fRegValues.Delete();
00916       f->SQLDeleteStatement(fRegStmt);
00917    }
00918 
00919    Long64_t GetNextObjId() { return ++fLastObjId; }
00920 
00921    void AddSqlCmd(const char* query)
00922    {
00923       // add SQL command to the list
00924       if (fCmds==0) fCmds = new TObjArray;
00925       fCmds->Add(new TObjString(query));
00926    }
00927 
00928    TSqlCmdsBuffer* GetCmdsBuffer(TSQLClassInfo* sqlinfo)
00929    {
00930       if (sqlinfo==0) return 0;
00931       TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
00932       if (buf==0) {
00933          buf = new TSqlCmdsBuffer(f, sqlinfo);
00934          fPool.Add(sqlinfo, buf);
00935       }
00936       return buf;
00937    }
00938 
00939    void ConvertSqlValues(TObjArray& values, const char* tablename)
00940    {
00941    // this function transforms array of values for one table
00942    // to SQL command. For MySQL one INSERT querie can
00943    // contain data for more than one row
00944 
00945       if ((values.GetLast()<0) || (tablename==0)) return;
00946 
00947       Bool_t canbelong = f->IsMySQL();
00948 
00949       Int_t maxsize = 50000;
00950       TString sqlcmd(maxsize), value, onecmd, cmdmask;
00951 
00952       const char* quote = f->SQLIdentifierQuote();
00953 
00954       TIter iter(&values);
00955       TObject* cmd = 0;
00956       while ((cmd = iter())!=0) {
00957 
00958          if (sqlcmd.Length()==0)
00959             sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)",
00960                         quote, tablename, quote, cmd->GetName());
00961          else {
00962             sqlcmd+=", (";
00963             sqlcmd += cmd->GetName();
00964             sqlcmd+=")";
00965          }
00966 
00967          if (!canbelong || (sqlcmd.Length()>maxsize*0.9)) {
00968             AddSqlCmd(sqlcmd.Data());
00969             sqlcmd = "";
00970          }
00971       }
00972 
00973       if (sqlcmd.Length()>0) AddSqlCmd(sqlcmd.Data());
00974    }
00975 
00976    void ConvertPoolValues()
00977    {
00978       TSQLClassInfo* sqlinfo = 0;
00979       TIter iter(&fPool);
00980       while ((sqlinfo = (TSQLClassInfo*) iter())!=0) {
00981          TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
00982          if (buf==0) continue;
00983          ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName());
00984          // ensure that raw table will be created
00985          if (buf->fBlobCmds.GetLast()>=0) f->CreateRawTable(sqlinfo);
00986          ConvertSqlValues(buf->fBlobCmds, sqlinfo->GetRawTableName());
00987          if (buf->fBlobStmt)
00988             buf->fBlobStmt->Process();
00989          if (buf->fNormStmt)
00990             buf->fNormStmt->Process();
00991       }
00992 
00993       ConvertSqlValues(fLongStrValues, sqlio::StringsTable);
00994       ConvertSqlValues(fRegValues, sqlio::ObjectsTable);
00995       if (fRegStmt) fRegStmt->Process();
00996    }
00997 
00998 
00999    void AddRegCmd(Long64_t objid, TClass* cl)
01000    {
01001       Long64_t indx = objid-fFirstObjId;
01002       if (indx<0) {
01003          Error("AddRegCmd","Something wrong with objid = %lld", objid);
01004          return;
01005       }
01006       
01007       if (f->IsOracle() || f->IsODBC()) {
01008          if ((fRegStmt==0) && f->SQLCanStatement()) {
01009             const char* quote = f->SQLIdentifierQuote();
01010             
01011             TString sqlcmd;
01012             const char* pars = f->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
01013             sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", 
01014                      quote, sqlio::ObjectsTable, quote, pars);
01015             fRegStmt = f->SQLStatement(sqlcmd.Data(), 1000);
01016          }
01017          
01018          if (fRegStmt!=0) {
01019             fRegStmt->NextIteration();
01020             fRegStmt->SetLong64(0, fKeyId);
01021             fRegStmt->SetLong64(1, objid);
01022             fRegStmt->SetString(2, cl->GetName(), f->SQLSmallTextTypeLimit());
01023             fRegStmt->SetInt(3, cl->GetClassVersion());
01024             return;
01025          }
01026       }      
01027       
01028       const char* valuequote = f->SQLValueQuote();
01029       TString cmd;
01030       cmd.Form("%lld, %lld, %s%s%s, %d",
01031                 fKeyId, objid,
01032                 valuequote, cl->GetName(), valuequote,
01033                 cl->GetClassVersion());
01034       fRegValues.AddAtAndExpand(new TObjString(cmd), indx);
01035    }
01036 
01037    Int_t AddLongString(const char* strvalue)
01038    {
01039       // add value to special string table,
01040       // where large (more than 255 bytes) strings are stored
01041 
01042       if (fLastLongStrId==0) f->VerifyLongStringTable();
01043       Int_t strid = ++fLastLongStrId;
01044       TString value = strvalue;
01045       const char* valuequote = f->SQLValueQuote();
01046       TSQLStructure::AddStrBrackets(value, valuequote);
01047 
01048       TString cmd;
01049       cmd.Form("%lld, %d, %s", fCurrentObjId, strid, value.Data());
01050 
01051       fLongStrValues.Add(new TObjString(cmd));
01052 
01053       return strid;
01054    }
01055 
01056    Bool_t InsertToNormalTableOracle(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
01057    {
01058       TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
01059       if (buf==0) return kFALSE;
01060       
01061       TSQLStatement* stmt = buf->fNormStmt;
01062       if (stmt==0) {
01063          // if one cannot create statement, do it normal way
01064          if (!f->SQLCanStatement()) return kFALSE;
01065          
01066          const char* quote = f->SQLIdentifierQuote();
01067          TString sqlcmd;
01068          sqlcmd.Form("INSERT INTO %s%s%s VALUES (", 
01069                      quote, sqlinfo->GetClassTableName(), quote);
01070          for (int n=0;n<columns->GetNumColumns();n++) {
01071             if (n>0) sqlcmd +=", ";
01072             if (f->IsOracle()) {
01073                sqlcmd += ":"; 
01074                sqlcmd += (n+1);
01075             } else
01076                sqlcmd += "?";
01077          }
01078          sqlcmd += ")";
01079                      
01080          stmt = f->SQLStatement(sqlcmd.Data(), 1000);
01081          if (stmt==0) return kFALSE;
01082          buf->fNormStmt = stmt;
01083       }
01084       
01085       stmt->NextIteration(); 
01086       
01087       Int_t sizelimit = f->SQLSmallTextTypeLimit();
01088        
01089       for (Int_t ncol=0;ncol<columns->GetNumColumns();ncol++) {
01090          const char* value = columns->GetColumn(ncol);
01091          if (value==0) value = "";
01092          stmt->SetString(ncol, value, sizelimit);
01093       }
01094       
01095       return kTRUE;
01096    }
01097 
01098    void InsertToNormalTable(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
01099    {
01100       // produce SQL query to insert object data into normal table
01101 
01102       if (f->IsOracle() || f->IsODBC())
01103          if (InsertToNormalTableOracle(columns, sqlinfo))
01104            return;
01105 
01106       const char* valuequote = f->SQLValueQuote();
01107 
01108       TString values;
01109       
01110       for (Int_t n=0;n<columns->GetNumColumns();n++) {
01111          if (n>0) values+=", "; 
01112          
01113          if (columns->IsNumeric(n))
01114             values+=columns->GetColumn(n);
01115          else {
01116             TString value = columns->GetColumn(n);
01117             TSQLStructure::AddStrBrackets(value, valuequote);
01118             values += value;
01119          }
01120       }
01121      
01122       TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
01123       if (buf!=0) buf->AddValues(kTRUE, values.Data());
01124    }
01125 };
01126 
01127 
01128 //_____________________________________________________________________________
01129 
01130 // TSqlRawBuffer is used to convert raw data, which corresponds to one
01131 // object and belong to single SQL tables. Supoorts both statements 
01132 // and query mode
01133 
01134 class TSqlRawBuffer : public TObject {
01135 
01136 public:
01137 
01138    TSqlRawBuffer(TSqlRegistry* reg, TSQLClassInfo* sqlinfo) :
01139       TObject(),
01140       fFile(0),
01141       fInfo(0),
01142       fCmdBuf(0),
01143       fObjId(0),
01144       fRawId(0),
01145       fValueMask(),
01146       fValueQuote(0),
01147       fMaxStrSize(255)
01148    {
01149       fFile = reg->f;
01150       fInfo = sqlinfo;
01151       fCmdBuf = reg->GetCmdsBuffer(sqlinfo);
01152       fObjId = reg->fCurrentObjId;
01153       fValueQuote = fFile->SQLValueQuote();
01154       fValueMask.Form("%lld, %s, %s%s%s, %s", fObjId, "%d", fValueQuote, "%s", fValueQuote, "%s");      
01155       fMaxStrSize = reg->f->SQLSmallTextTypeLimit();
01156    }
01157    
01158    virtual ~TSqlRawBuffer() 
01159    {
01160       // close blob statement for Oracle
01161       TSQLStatement* stmt = fCmdBuf->fBlobStmt;
01162       if ((stmt!=0) && fFile->IsOracle()) {
01163          stmt->Process();
01164          delete stmt;
01165          fCmdBuf->fBlobStmt = 0;
01166       }
01167    }
01168    
01169    Bool_t IsAnyData() const { return fRawId>0; }
01170 
01171    void AddLine(const char* name, const char* value, const char* topname = 0, const char* ns = 0)
01172    {
01173       if (fCmdBuf==0) return;
01174       
01175       // when first line is created, check all problems
01176       if (fRawId==0) {
01177          Bool_t maketmt = kFALSE;
01178          if (fFile->IsOracle() || fFile->IsODBC())
01179             maketmt = (fCmdBuf->fBlobStmt==0) && fFile->SQLCanStatement();
01180             
01181          if (maketmt) {
01182             // ensure that raw table is exists
01183             fFile->CreateRawTable(fInfo);
01184             
01185             const char* quote = fFile->SQLIdentifierQuote();
01186             TString sqlcmd;
01187             const char* params = fFile->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
01188             sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", 
01189                         quote, fInfo->GetRawTableName(), quote, params);
01190             TSQLStatement* stmt = fFile->SQLStatement(sqlcmd.Data(), 2000);
01191             fCmdBuf->fBlobStmt = stmt;
01192          }
01193       }
01194       
01195       TString buf;
01196       const char* fullname = name;
01197       if ((topname!=0) && (ns!=0)) {
01198          buf+=topname;
01199          buf+=ns;
01200          buf+=name;
01201          fullname = buf.Data();
01202       }
01203       
01204       TSQLStatement* stmt = fCmdBuf->fBlobStmt;
01205       
01206       if (stmt!=0) {
01207          stmt->NextIteration();
01208          stmt->SetLong64(0, fObjId);
01209          stmt->SetInt(1, fRawId++);
01210          stmt->SetString(2, fullname, fMaxStrSize);
01211 //         Info("AddLine","name = %s value = %s",fullname, value);
01212          stmt->SetString(3, value, fMaxStrSize);
01213       } else {
01214          TString valuebuf(value);
01215          TSQLStructure::AddStrBrackets(valuebuf, fValueQuote);
01216          TString cmd;
01217          cmd.Form(fValueMask.Data(), fRawId++, fullname, valuebuf.Data());
01218          fCmdBuf->AddValues(kFALSE, cmd.Data());         
01219       }
01220    }
01221       
01222    TSQLFile*  fFile;
01223    TSQLClassInfo* fInfo;
01224    TSqlCmdsBuffer* fCmdBuf;
01225    Long64_t fObjId; 
01226    Int_t fRawId;
01227    TString fValueMask;
01228    const char* fValueQuote;
01229    Int_t fMaxStrSize;
01230 };
01231 
01232 //________________________________________________________________________
01233 Long64_t TSQLStructure::FindMaxObjectId()
01234 {
01235    // define maximum reference id, used for objects
01236 
01237    Long64_t max = DefineObjectId(kFALSE);
01238 
01239    for (Int_t n=0;n<NumChilds();n++) {
01240       Long64_t zn = GetChild(n)->FindMaxObjectId();
01241       if (zn>max) max = zn;
01242    }
01243 
01244    return max;
01245 }
01246 
01247 //________________________________________________________________________
01248 Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Long64_t keyid, TObjArray* cmds)
01249 {
01250    // Convert structure to sql statements
01251    // This function is called immidiately after TBufferSQL2 produces
01252    // this structure with object data
01253    // Should be only called for toplevel structure
01254 
01255    if ((file==0) || (cmds==0)) return kFALSE;
01256 
01257    TSqlRegistry reg;
01258 
01259    reg.fCmds = cmds;
01260    reg.f = file;
01261    reg.fKeyId = keyid;
01262    // this is id of main object to be stored
01263    reg.fFirstObjId = DefineObjectId(kFALSE);
01264    // this is maximum objectid which is now in use
01265    reg.fLastObjId = FindMaxObjectId();
01266 
01267    Bool_t res = StoreObject(&reg, reg.fFirstObjId, GetObjectClass());
01268 
01269    // convert values from pool to SQL commands
01270    reg.ConvertPoolValues();
01271 
01272    return res;
01273 }
01274 
01275 //________________________________________________________________________
01276 void TSQLStructure::PerformConversion(TSqlRegistry* reg, TSqlRawBuffer* blobs, const char* topname, Bool_t useblob)
01277 {
01278    // perform conversion of structure to sql statements
01279    // first tries convert it to normal form
01280    // if fails, produces data for raw table
01281 
01282    TString sbuf;
01283    const char* ns = reg->f->SQLNameSeparator();
01284 
01285    switch (fType) {
01286    case kSqlObject: {
01287 
01288       if (!StoreObject(reg, DefineObjectId(kFALSE), GetObjectClass())) break;
01289 
01290       blobs->AddLine(sqlio::ObjectRef, GetValue(), topname, ns);
01291 
01292       break;
01293    }
01294 
01295    case kSqlPointer: {
01296       blobs->AddLine(sqlio::ObjectPtr, fValue.Data(), topname,ns);
01297       break;
01298    }
01299 
01300    case kSqlVersion: {
01301       if (fPointer!=0)
01302          topname = ((TClass*) fPointer)->GetName();
01303       else
01304          Error("PerformConversion","version without class");
01305       blobs->AddLine(sqlio::Version, fValue.Data(), topname, ns);
01306       break;
01307    }
01308 
01309    case kSqlStreamerInfo: {
01310 
01311       TStreamerInfo* info = GetStreamerInfo();
01312       if (info==0) return;
01313 
01314       if (useblob) {
01315          for(Int_t n=0;n<=fChilds.GetLast();n++) {
01316             TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
01317             child->PerformConversion(reg, blobs, info->GetName(), useblob);
01318          }
01319       } else {
01320          Long64_t objid = reg->GetNextObjId();
01321          TString sobjid;
01322          sobjid.Form("%lld",objid);
01323          if (!StoreObject(reg, objid, info->GetClass(), kTRUE)) return;
01324          blobs->AddLine(sqlio::ObjectInst, sobjid.Data(), topname, ns);
01325       }
01326       break;
01327    }
01328 
01329    case kSqlCustomElement:
01330    case kSqlElement: {
01331       const TStreamerElement* elem = (const TStreamerElement*) fPointer;
01332 
01333       Int_t indx = 0;
01334       while (indx<NumChilds()) {
01335          TSQLStructure* child = GetChild(indx++);
01336          child->PerformConversion(reg, blobs, elem->GetName(), useblob);
01337       }
01338       break;
01339    }
01340 
01341    case kSqlValue: {
01342       const char* tname = (const char*) fPointer;
01343       if (fArrayIndex>=0) {
01344          if (fRepeatCnt>1)
01345             sbuf.Form("%s%d%s%d%s%s%s", "[", fArrayIndex, sqlio::IndexSepar, fArrayIndex+fRepeatCnt-1, "]", ns, tname);
01346          else
01347             sbuf.Form("%s%d%s%s%s", "[", fArrayIndex, "]", ns, tname);
01348       } else {
01349          if (tname!=0) sbuf = tname;
01350          else sbuf = "Value";
01351       }
01352 
01353       TString buf;
01354       const char* value = fValue.Data();
01355 
01356       if ((tname==sqlio::CharStar) && (value!=0)) {
01357          Int_t size = strlen(value);
01358          if (size > reg->f->SQLSmallTextTypeLimit()) {
01359             Int_t strid = reg->AddLongString(value);
01360             buf = reg->f->CodeLongString(reg->fCurrentObjId, strid);
01361             value = buf.Data();
01362          }
01363       }
01364 
01365       blobs->AddLine(sbuf.Data(), value, (fArrayIndex>=0) ? 0 : topname, ns);
01366 
01367       break;
01368    }
01369 
01370    case kSqlArray: {
01371       if (fValue.Length()>0)
01372          blobs->AddLine(sqlio::Array, fValue.Data(), topname, ns);
01373       for(Int_t n=0;n<=fChilds.GetLast();n++) {
01374          TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
01375          child->PerformConversion(reg, blobs, topname, useblob);
01376       }
01377       break;
01378    }
01379    }
01380 }
01381 
01382 //________________________________________________________________________
01383 Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl, Bool_t registerobj)
01384 {
01385    // convert object data to sql statements
01386    // if normal (columnwise) representation is not possible,
01387    // complete object will be converted to raw format
01388 
01389    if ((cl==0) || (objid<0)) return kFALSE;
01390 
01391    if (gDebug>1) {
01392       cout << "Store object " << objid <<" cl = " << cl->GetName() << endl;
01393       if (GetStreamerInfo()) cout << "Info = " << GetStreamerInfo()->GetName() << endl; else
01394          if (GetElement()) cout << "Element = " << GetElement()->GetName() << endl;
01395    }
01396 
01397    Long64_t oldid = reg->fCurrentObjId;
01398    TClass* oldcl = reg->fCurrentObjClass;
01399 
01400    reg->fCurrentObjId = objid;
01401    reg->fCurrentObjClass = cl;
01402 
01403    Bool_t normstore = kFALSE;
01404 
01405    Bool_t res = kTRUE;
01406 
01407    if (cl==TObject::Class())
01408       normstore = StoreTObject(reg);
01409    else
01410    if (cl==TString::Class())
01411       normstore = StoreTString(reg);
01412    else
01413       if (GetType()==kSqlStreamerInfo)
01414          // this is a case when array of objects are stored in blob and each object
01415          // has normal streamer. Then it will be stored in normal form and only one tag
01416          // will be kept to remind about
01417          normstore = StoreClassInNormalForm(reg);
01418       else
01419          normstore = StoreObjectInNormalForm(reg);
01420 
01421    if (gDebug>2)
01422       cout << "Store object " << objid << " of class " << cl->GetName() << "  normal = " << normstore << " sqltype = " << GetType() << endl;
01423 
01424    if (!normstore) {
01425 
01426       // This is a case, when only raw table is exists
01427 
01428       TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl);
01429       TSqlRawBuffer rawdata(reg, sqlinfo);
01430 
01431       for(Int_t n=0;n<NumChilds();n++) {
01432          TSQLStructure* child = GetChild(n);
01433          child->PerformConversion(reg, &rawdata, 0 /*cl->GetName()*/);
01434       }
01435 
01436       res = rawdata.IsAnyData();
01437    }
01438 
01439    if (registerobj)
01440       reg->AddRegCmd(objid, cl);
01441 
01442    reg->fCurrentObjId = oldid;
01443    reg->fCurrentObjClass = oldcl;
01444 
01445    return res;
01446 }
01447 
01448 //________________________________________________________________________
01449 Bool_t TSQLStructure::StoreObjectInNormalForm(TSqlRegistry* reg)
01450 {
01451    // this function verify object child elements and
01452    // calls transformation to class table
01453 
01454    if (fChilds.GetLast()!=1) return kFALSE;
01455 
01456    TSQLStructure* s_ver = GetChild(0);
01457 
01458    TSQLStructure* s_info = GetChild(1);
01459 
01460    if (!CheckNormalClassPair(s_ver, s_info)) return kFALSE;
01461 
01462    return s_info->StoreClassInNormalForm(reg);
01463 }
01464 
01465 //________________________________________________________________________
01466 Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg)
01467 {
01468    // produces data for complete class table
01469    // where not possible, raw data for some elements are created
01470 
01471    TClass* cl = 0;
01472    Version_t version = 0;
01473    if (!GetClassInfo(cl, version)) return kFALSE;
01474    if (cl==0) return kFALSE;
01475 
01476    TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl->GetName(), version);
01477 
01478    TSQLTableData columns(reg->f, sqlinfo);
01479    Bool_t needblob = kFALSE;
01480 
01481    TSqlRawBuffer rawdata(reg, sqlinfo);
01482 
01483 //   Int_t currrawid = 0;
01484 
01485    // add first column with object id
01486    columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
01487 
01488    for(Int_t n=0;n<=fChilds.GetLast();n++) {
01489       TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
01490       TStreamerElement* elem = child->GetElement();
01491 
01492       if (elem==0) {
01493          Error("StoreClassInNormalForm", "CAN NOT BE");
01494          continue;
01495       }
01496 
01497       if (child->StoreElementInNormalForm(reg, &columns)) continue;
01498 
01499       Int_t columntyp = DefineElementColumnType(elem, reg->f);
01500       if ((columntyp!=kColRawData) && (columntyp!=kColObjectArray)) {
01501          Error("StoreClassInNormalForm","Element %s typ=%d has problem with normal store ", elem->GetName(), columntyp);
01502          continue;
01503       }
01504 
01505 
01506       Bool_t doblobs = kTRUE;
01507 
01508       Int_t blobid = rawdata.fRawId; // keep id of first raw, used in class table 
01509 
01510       if (columntyp==kColObjectArray)
01511          if (child->TryConvertObjectArray(reg, &rawdata))
01512             doblobs = kFALSE;
01513 
01514       if (doblobs)
01515          child->PerformConversion(reg, &rawdata, elem->GetName(), kFALSE);
01516 
01517       if (blobid==rawdata.fRawId) 
01518          blobid = -1; // no data for blob was created
01519       else { 
01520          //reg->f->CreateRawTable(sqlinfo);
01521          //blobid = currrawid; // column will contain first raw id
01522          //reg->ConvertBlobs(&blobs, sqlinfo, currrawid);
01523          needblob = kTRUE;
01524       }
01525       //blobs.Delete();
01526 
01527       TString blobname = elem->GetName();
01528       if (reg->f->GetUseSuffixes())
01529          blobname += sqlio::RawSuffix;
01530 
01531       columns.AddColumn(blobname, blobid);
01532    }
01533 
01534    reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
01535 
01536    reg->InsertToNormalTable(&columns, sqlinfo);
01537 
01538    return kTRUE;
01539 }
01540 
01541 //________________________________________________________________________
01542 TString TSQLStructure::MakeArrayIndex(TStreamerElement* elem, Int_t index)
01543 {
01544    // produce string with complete index like [1][2][0]
01545 
01546    TString res;
01547    if ((elem==0) || (elem->GetArrayLength()==0)) return res;
01548 
01549    for(Int_t ndim=elem->GetArrayDim()-1;ndim>=0;ndim--) {
01550       Int_t ix = index % elem->GetMaxIndex(ndim);
01551       index = index / elem->GetMaxIndex(ndim);
01552       TString buf;
01553       buf.Form("%s%d%s","[",ix,"]");
01554       res = buf + res;
01555    }
01556    return res;
01557 }
01558 
01559 //________________________________________________________________________
01560 Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TSQLTableData* columns)
01561 {
01562    // tries to store element data in column
01563 
01564    TStreamerElement* elem = GetElement();
01565    if (elem==0) return kFALSE;
01566 
01567    Int_t typ = elem->GetType();
01568 
01569    Int_t columntyp = DefineElementColumnType(elem, reg->f);
01570 
01571    if (gDebug>4)
01572       cout << "Element " << elem->GetName()
01573            << "   type = " << typ
01574            << "  column = " << columntyp << endl;
01575 
01576    TString colname = DefineElementColumnName(elem, reg->f);
01577 
01578    if (columntyp==kColTString) {
01579       const char* value;
01580       if (!RecognizeTString(value)) return kFALSE;
01581 
01582       Int_t len = value ? strlen(value) : 0;
01583 
01584       Int_t sizelimit = reg->f->SQLSmallTextTypeLimit();
01585 
01586       const char* stype = reg->f->SQLSmallTextType();
01587 
01588       if (len<=sizelimit)
01589          columns->AddColumn(colname.Data(), stype, value, kFALSE);
01590       else {
01591          Int_t strid = reg->AddLongString(value);
01592          TString buf = reg->f->CodeLongString(reg->fCurrentObjId, strid);
01593          columns->AddColumn(colname.Data(), stype, buf.Data(), kFALSE);
01594       }
01595 
01596       return kTRUE;
01597    }
01598 
01599    if (columntyp==kColParent) {
01600       Long64_t objid = reg->fCurrentObjId;
01601       TClass* basecl = elem->GetClassPointer();
01602       Int_t resversion = basecl->GetClassVersion();
01603       if (!StoreObject(reg, objid, basecl, kFALSE))
01604          resversion = -1;
01605       columns->AddColumn(colname.Data(), resversion);
01606       return kTRUE;
01607    }
01608 
01609    if (columntyp==kColObject) {
01610 
01611       Long64_t objid = -1;
01612 
01613       if (NumChilds()==1) {
01614          TSQLStructure* child = GetChild(0);
01615 
01616          if (child->GetType()==kSqlObject) {
01617             objid = child->DefineObjectId(kFALSE);
01618             if (!child->StoreObject(reg, objid, child->GetObjectClass())) return kFALSE;
01619          } else
01620          if (child->GetType()==kSqlPointer) {
01621             TString sobjid = child->GetValue();
01622             if (sobjid.Length()>0)
01623                objid = sqlio::atol64(sobjid.Data());
01624          }
01625       }
01626 
01627       if (objid<0) {
01628          //cout << "!!!! Not standard " << elem->GetName() << " class = " << elem->GetClassPointer()->GetName() << endl;
01629          objid = reg->GetNextObjId();
01630          if (!StoreObject(reg, objid, elem->GetClassPointer()))
01631             objid = -1;  // this is a case, when no data was stored for this object
01632       }
01633 
01634       columns->AddColumn(colname.Data(), objid);
01635       return kTRUE;
01636    }
01637 
01638    if (columntyp==kColNormObject) {
01639 
01640       if (NumChilds()!=1) {
01641          Error("kColNormObject","NumChilds()=%d", NumChilds());
01642          PrintLevel(20);
01643          return kFALSE;
01644       }
01645       TSQLStructure* child = GetChild(0);
01646       if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE;
01647 
01648       Bool_t normal = kTRUE;
01649 
01650       Long64_t objid = -1;
01651 
01652       if (child->GetType()==kSqlObject) {
01653          objid = child->DefineObjectId(kFALSE); 
01654          normal = child->StoreObject(reg, objid, child->GetObjectClass());
01655       } else {
01656          objid = child->DefineObjectId(kFALSE);
01657       }
01658 
01659       if (!normal) {
01660          Error("kColNormObject","child->StoreObject fails");
01661          return kFALSE;
01662       }
01663 
01664       columns->AddColumn(colname.Data(), objid);
01665       return kTRUE;
01666    }
01667 
01668    if (columntyp==kColNormObjectArray) {
01669        
01670       if (elem->GetArrayLength()!=NumChilds()) return kFALSE;
01671 
01672       for (Int_t index=0;index<NumChilds();index++) {
01673          TSQLStructure* child = GetChild(index);
01674          if ((child->GetType()!=kSqlPointer) &&
01675              (child->GetType()!=kSqlObject)) return kFALSE;
01676          Bool_t normal = kTRUE;
01677 
01678          Long64_t objid = child->DefineObjectId(kFALSE);
01679 
01680          if (child->GetType()==kSqlObject)
01681             normal = child->StoreObject(reg, objid, child->GetObjectClass());
01682 
01683          if (!normal) return kFALSE;
01684 
01685          colname = DefineElementColumnName(elem, reg->f, index);
01686 
01687          columns->AddColumn(colname.Data(), objid);
01688       }
01689       return kTRUE;
01690    }
01691 
01692    if (columntyp==kColObjectPtr) {
01693       if (NumChilds()!=1) return kFALSE;
01694       TSQLStructure* child = GetChild(0);
01695       if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE;
01696 
01697       Bool_t normal = kTRUE;
01698       Long64_t objid = -1;
01699 
01700       if (child->GetType()==kSqlObject) {
01701          objid = child->DefineObjectId(kFALSE);
01702          normal = child->StoreObject(reg, objid, child->GetObjectClass());
01703       }
01704 
01705       if (!normal) return kFALSE;
01706 
01707       columns->AddColumn(colname.Data(), objid);
01708       return kTRUE;
01709    }
01710 
01711    if (columntyp==kColSimple) {
01712 
01713       // only child shoud existing for element
01714       if (NumChilds()!=1) {
01715          Error("StoreElementInNormalForm","Enexpected number %d for simple element %s", NumChilds(), elem->GetName());
01716          return kFALSE;
01717       }
01718 
01719       TSQLStructure* child = GetChild(0);
01720       if (child->GetType()!=kSqlValue) return kFALSE;
01721 
01722       const char* value = child->GetValue();
01723       if (value==0) return kFALSE;
01724 
01725       const char* sqltype = reg->f->SQLCompatibleType(typ);
01726 
01727       columns->AddColumn(colname.Data(), sqltype, value, IsNumericType(typ));
01728 
01729       return kTRUE;
01730    }
01731 
01732    if (columntyp==kColSimpleArray) {
01733       // number of items should be exactly equal to number of childs
01734 
01735       if (NumChilds()!=1) {
01736          Error("StoreElementInNormalForm","In fixed array %s only array node should be", elem->GetName());
01737          return kFALSE;
01738       }
01739       TSQLStructure* arr = GetChild(0);
01740 
01741       const char* sqltype = reg->f->SQLCompatibleType(typ % 20);
01742 
01743       for(Int_t n=0;n<arr->NumChilds();n++) {
01744          TSQLStructure* child = arr->GetChild(n);
01745          if (child->GetType()!=kSqlValue) return kFALSE;
01746 
01747          const char* value = child->GetValue();
01748          if (value==0) return kFALSE;
01749 
01750          Int_t index = child->GetArrayIndex();
01751          Int_t last = index + child->GetRepeatCounter();
01752 
01753          while (index<last) {
01754             colname = DefineElementColumnName(elem, reg->f, index);
01755             columns->AddColumn(colname.Data(), sqltype, value, kTRUE);
01756             index++;
01757          }
01758       }
01759       return kTRUE;
01760    }
01761 
01762    return kFALSE;
01763 }
01764 
01765 //________________________________________________________________________
01766 Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TSqlRawBuffer* blobs)
01767 {
01768    // tries to write array of objects as lis of object refereneces
01769    // in _streamer_ table, while objects itself will be stored in
01770    // other tables. If not successfull, object data will be stored
01771    // in _streamer_ table
01772 
01773    TStreamerElement* elem = GetElement();
01774    if (elem==0) return kFALSE;
01775 
01776    if (NumChilds() % 2 !=0) return kFALSE;
01777 
01778    Int_t indx = 0;
01779 
01780    while (indx<NumChilds()) {
01781       TSQLStructure* s_ver = GetChild(indx++);
01782       TSQLStructure* s_info = GetChild(indx++);
01783       if (!CheckNormalClassPair(s_ver, s_info)) return kFALSE;
01784    }
01785 
01786    indx = 0;
01787    const char* ns = reg->f->SQLNameSeparator();
01788 
01789    while (indx<NumChilds()-1) {
01790       indx++; //TSQLStructure* s_ver = GetChild(indx++);
01791       TSQLStructure* s_info = GetChild(indx++);
01792       TClass* cl = 0;
01793       Version_t version = 0;
01794       if (!s_info->GetClassInfo(cl, version)) return kFALSE;
01795       Long64_t objid = reg->GetNextObjId();
01796       if (!s_info->StoreObject(reg, objid, cl))
01797          objid = -1;  // this is a case, when no data was stored for this object
01798 
01799       TString sobjid;
01800       sobjid.Form("%lld", objid);
01801 
01802       blobs->AddLine(sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns);
01803    }
01804 
01805    return kTRUE;
01806 }
01807 
01808 //________________________________________________________________________
01809 Bool_t TSQLStructure::CheckNormalClassPair(TSQLStructure* s_ver, TSQLStructure* s_info)
01810 {
01811    // check if pair of two element corresponds
01812    // to start of object, stored in normal form
01813 
01814    if ((s_ver==0) || (s_info==0) || (s_ver->GetType()!=kSqlVersion)) return kFALSE;
01815 
01816    TClass* ver_cl = s_ver->GetVersionClass();
01817 
01818    TClass* info_cl = 0;
01819    Version_t info_ver = 0;
01820    if (!s_info->GetClassInfo(info_cl, info_ver)) return kFALSE;
01821 
01822    if ((ver_cl==0) || (info_cl==0) || (ver_cl!=info_cl) ||
01823        (ver_cl->GetClassVersion()!=info_ver)) return kFALSE;
01824 
01825    return kTRUE;
01826 }
01827 
01828 //________________________________________________________________________
01829 Bool_t TSQLStructure::StoreTObject(TSqlRegistry* reg)
01830 {
01831    // store data of TObject in special table
01832    // workaround custom TObject streamer
01833 
01834    // check if it is really Looks like TObject data
01835    if ((NumChilds()<3) || (NumChilds()>4)) return kFALSE;
01836 
01837    TSQLStructure* str_ver  = GetChild(0);
01838    TSQLStructure* str_id   = GetChild(1);
01839    TSQLStructure* str_bits = GetChild(2);
01840    TSQLStructure* str_prid = GetChild(3);
01841 
01842    if (str_ver->GetType()!=kSqlVersion) return kFALSE;
01843    if ((str_id->GetType()!=kSqlValue) ||
01844        (str_id->GetValueType()!=sqlio::UInt)) return kFALSE;
01845    if ((str_bits->GetType()!=kSqlValue) ||
01846        (str_bits->GetValueType()!=sqlio::UInt)) return kFALSE;
01847    if (str_prid!=0)
01848       if ((str_prid->GetType()!=kSqlValue) ||
01849           (str_prid->GetValueType()!=sqlio::UShort)) return kFALSE;
01850 
01851    TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(TObject::Class());
01852 
01853    if (sqlinfo==0) return kFALSE;
01854 
01855    TSQLTableData columns(reg->f, sqlinfo);
01856 
01857    const char* uinttype = reg->f->SQLCompatibleType(TStreamerInfo::kUInt);
01858 
01859    columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
01860 
01861    columns.AddColumn(sqlio::TObjectUniqueId, uinttype, str_id->GetValue(), kTRUE);
01862    columns.AddColumn(sqlio::TObjectBits, uinttype, str_bits->GetValue(), kTRUE);
01863    columns.AddColumn(sqlio::TObjectProcessId, "CHAR(3)", (str_prid ? str_prid->GetValue() : ""), kFALSE);
01864 
01865    reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
01866 
01867    reg->InsertToNormalTable(&columns, sqlinfo);
01868 
01869    return kTRUE;
01870 }
01871 
01872 //________________________________________________________________________
01873 Bool_t TSQLStructure::StoreTString(TSqlRegistry* reg)
01874 {
01875    // store data of TString in special table
01876    // it is required when TString stored as pointer and reference to it possible
01877 
01878    const char* value = 0;
01879    if (!RecognizeTString(value)) return kFALSE;
01880 
01881    TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(TString::Class());
01882    if (sqlinfo==0) return kFALSE;
01883 
01884    TSQLTableData columns(reg->f, sqlinfo);
01885 
01886    columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
01887    columns.AddColumn(sqlio::TStringValue, reg->f->SQLBigTextType(), value, kFALSE);
01888 
01889    reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
01890    
01891    reg->InsertToNormalTable(&columns, sqlinfo);
01892    return kTRUE;
01893 }
01894 
01895 //________________________________________________________________________
01896 Bool_t TSQLStructure::RecognizeTString(const char* &value)
01897 {
01898    // prove that structure containes TString data
01899 
01900    value = 0;
01901 
01902    if ((NumChilds()==0) || (NumChilds()>3)) return kFALSE;
01903 
01904    TSQLStructure *len=0, *lenbig=0, *chars=0;
01905    for (Int_t n=0;n<NumChilds();n++) {
01906       TSQLStructure* curr = GetChild(n);
01907       if (curr->fType!=kSqlValue) return kFALSE;
01908       if (curr->fPointer==sqlio::UChar) {
01909          if (len==0) len=curr; else return kFALSE;
01910       } else
01911          if (curr->fPointer==sqlio::Int) {
01912             if (lenbig==0) lenbig=curr; else return kFALSE;
01913          } else
01914             if (curr->fPointer==sqlio::CharStar) {
01915                if (chars==0) chars=curr; else return kFALSE;
01916             } else return kFALSE;
01917    }
01918 
01919    if (len==0) return kFALSE;
01920    if ((lenbig!=0) && ((chars==0) || (len==0))) return kFALSE;
01921 
01922    if (chars!=0)
01923       value = chars->GetValue();
01924 
01925    return kTRUE;
01926 }
01927 
01928 //________________________________________________________________________
01929 Int_t TSQLStructure::DefineElementColumnType(TStreamerElement* elem, TSQLFile* f)
01930 {
01931    // defines which kind of column can be assigned for this element
01932    // Possible cases
01933    //    kColSimple       -  basic data type
01934    //    kColSimpleArray  -  fixed arary of basic types
01935    //    kColParent       -  parent class
01936    //    kColObject       -  object as data memeber
01937    //    kColObjectPtr    -  object as pointer
01938    //    kColTString      -  TString
01939    //    kColRawData      -  anything else as raw data
01940 
01941    if (elem==0) return kColUnknown;
01942 
01943    Int_t typ = elem->GetType();
01944 
01945    if (typ == TStreamerInfo::kMissing) return kColRawData;
01946 
01947    if ((typ>0) && (typ<20) &&
01948        (typ!=TStreamerInfo::kCharStar)) return kColSimple;
01949 
01950    if ((typ>TStreamerInfo::kOffsetL) &&
01951        (typ<TStreamerInfo::kOffsetP))
01952       if ((f->GetArrayLimit()<0) ||
01953           (elem->GetArrayLength()<=f->GetArrayLimit()))
01954          return kColSimpleArray;
01955 
01956    if (typ==TStreamerInfo::kTObject) {
01957       if (elem->InheritsFrom(TStreamerBase::Class()))
01958          return kColParent;
01959       else
01960          return kColObject;
01961    }
01962 
01963    if (typ==TStreamerInfo::kTNamed) {
01964       if (elem->InheritsFrom(TStreamerBase::Class()))
01965          return kColParent;
01966       else
01967          return kColObject;
01968    }
01969 
01970    if (typ==TStreamerInfo::kTString) return kColTString;
01971 
01972    if (typ==TStreamerInfo::kBase) return kColParent;
01973 
01974    if (typ==TStreamerInfo::kSTL)
01975       if (elem->InheritsFrom(TStreamerBase::Class()))
01976          return kColParent;
01977 
01978    // this is workaround
01979    // these two tags stored with WriteFastArray, but read with cl->Streamer()
01980    if ((typ==TStreamerInfo::kObject)  ||
01981        (typ==TStreamerInfo::kAny)) {
01982       if (elem->GetArrayLength()==0)
01983          return kColObject;
01984       else
01985          if (elem->GetStreamer()==0)
01986             return kColObjectArray;
01987    }
01988 
01989    if ((typ==TStreamerInfo::kObject)  ||
01990        (typ==TStreamerInfo::kAny) ||
01991        (typ==TStreamerInfo::kAnyp) ||
01992        (typ==TStreamerInfo::kObjectp) ||
01993        (typ==TStreamerInfo::kAnyP) ||
01994        (typ==TStreamerInfo::kObjectP)) {
01995       if ((elem->GetArrayLength()==0) ||
01996          (elem->GetStreamer()!=0))
01997          return kColNormObject;
01998       else
01999          return kColNormObjectArray;
02000    }
02001 
02002    if ((typ==TStreamerInfo::kObject + TStreamerInfo::kOffsetL) ||
02003        (typ==TStreamerInfo::kAny + TStreamerInfo::kOffsetL) ||
02004        (typ==TStreamerInfo::kAnyp + TStreamerInfo::kOffsetL) ||
02005        (typ==TStreamerInfo::kObjectp + TStreamerInfo::kOffsetL) ||
02006        (typ==TStreamerInfo::kAnyP + TStreamerInfo::kOffsetL) ||
02007        (typ==TStreamerInfo::kObjectP + TStreamerInfo::kOffsetL)) {
02008       if (elem->GetStreamer()!=0)
02009          return kColNormObject;
02010       else
02011          return kColNormObjectArray;
02012    }
02013 
02014    if ((typ==TStreamerInfo::kObject) ||
02015        (typ==TStreamerInfo::kAny) ||
02016        (typ==TStreamerInfo::kAnyp) ||
02017        (typ==TStreamerInfo::kObjectp) ||
02018        (typ==TStreamerInfo::kSTL)) {
02019       if (elem->GetArrayLength()==0)
02020          return kColObject;
02021       else
02022          if (elem->GetStreamer()==0)
02023             return kColObjectArray;
02024    }
02025 
02026    if (((typ==TStreamerInfo::kAnyP) ||
02027         (typ==TStreamerInfo::kObjectP)) &&
02028        (elem->GetArrayDim()==0)) return kColObjectPtr;
02029 
02030    //   if ((typ==TStreamerInfo::kSTLp) &&
02031    //       (elem->GetArrayDim()==0)) {
02032    //      TStreamerSTL* stl = dynamic_cast<TStreamerSTL*> (elem);
02033    //      if ((stl!=0) && (dynamic_cast<TStreamerSTLstring*>(elem)==0))
02034    //        return kColObjectPtr;
02035    //   }
02036 
02037    return kColRawData;
02038 }
02039 
02040 //________________________________________________________________________
02041 TString TSQLStructure::DefineElementColumnName(TStreamerElement* elem, TSQLFile* f, Int_t indx)
02042 {
02043    // returns name of the column in class table for that element
02044 
02045    TString colname = "";
02046 
02047    Int_t coltype = DefineElementColumnType(elem, f);
02048    if (coltype==kColUnknown) return colname;
02049 
02050    const char* elemname = elem->GetName();
02051 
02052    switch (coltype) {
02053    case kColSimple: {
02054       colname = elemname;
02055       if (f->GetUseSuffixes()) {
02056          colname+=f->SQLNameSeparator();
02057          colname+=GetSimpleTypeName(elem->GetType());
02058       }
02059       break;
02060    }
02061 
02062    case kColSimpleArray: {
02063       colname = elemname;
02064       colname+=MakeArrayIndex(elem, indx);
02065       break;
02066    }
02067 
02068    case kColParent: {
02069       colname = elemname;
02070       if (f->GetUseSuffixes())
02071          colname+=sqlio::ParentSuffix;
02072       break;
02073    }
02074 
02075    case kColNormObject: {
02076       colname = elemname;
02077       if (f->GetUseSuffixes())
02078          colname += sqlio::ObjectSuffix;
02079       break;
02080    }
02081 
02082    case kColNormObjectArray: {
02083       colname = elemname;
02084       colname+=MakeArrayIndex(elem, indx);
02085       if (f->GetUseSuffixes())
02086          colname += sqlio::ObjectSuffix;
02087       break;
02088    }
02089 
02090    case kColObject: {
02091       colname = elemname;
02092       if (f->GetUseSuffixes())
02093          colname += sqlio::ObjectSuffix;
02094       break;
02095    }
02096 
02097    case kColObjectPtr: {
02098       colname = elemname;
02099       if (f->GetUseSuffixes())
02100          colname += sqlio::PointerSuffix;
02101       break;
02102    }
02103 
02104    case kColTString: {
02105       colname = elem->GetName();
02106       if (f->GetUseSuffixes())
02107          colname+=sqlio::StrSuffix;
02108       break;
02109    }
02110 
02111    case kColRawData: {
02112       colname = elemname;
02113       if (f->GetUseSuffixes())
02114          colname += sqlio::RawSuffix;
02115       break;
02116    }
02117 
02118    case kColObjectArray: {
02119       colname = elemname;
02120       if (f->GetUseSuffixes())
02121          colname += sqlio::RawSuffix;
02122       break;
02123    }
02124    }
02125 
02126    return colname;
02127 }
02128 
02129 //________________________________________________________________________
02130 Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data)
02131 {
02132    // find column in TSQLObjectData object, which correspond to current element
02133 
02134    TStreamerElement* elem = GetElement();
02135    if ((elem==0) || (data==0)) return kColUnknown;
02136 
02137    Int_t coltype = DefineElementColumnType(elem, f);
02138 
02139    if (gDebug>4)
02140       cout <<"TSQLStructure::LocateElementColumn " << elem->GetName() <<
02141          " coltyp = " << coltype << " : " << elem->GetType() << " len = " << elem->GetArrayLength() << endl;
02142 
02143    if (coltype==kColUnknown) return kColUnknown;
02144 
02145    const char* elemname = elem->GetName();
02146    Bool_t located = kFALSE;
02147 
02148    TString colname = DefineElementColumnName(elem, f);
02149 
02150    if (gDebug>4)
02151       cout << "         colname = " << colname << " in " <<
02152             data->GetInfo()->GetClassTableName() << endl;
02153 
02154    switch (coltype) {
02155    case kColSimple: {
02156       located = data->LocateColumn(colname.Data());
02157       break;
02158    }
02159 
02160    case kColSimpleArray: {
02161       located = data->LocateColumn(colname);
02162       break;
02163    }
02164 
02165    case kColParent: {
02166       located = data->LocateColumn(colname.Data());
02167       if (located==kColUnknown) return kColUnknown;
02168 
02169       Long64_t objid = DefineObjectId(kTRUE);
02170       const char* clname = elemname;
02171       Version_t version = atoi(data->GetValue());
02172 
02173       // this is a case, when parent store nothing in the database
02174       if (version<0) break;
02175 
02176       // special treatment for TObject
02177       if (strcmp(clname,TObject::Class()->GetName())==0) {
02178          UnpackTObject(f, buf, data, objid, version);
02179          break;
02180       }
02181 
02182       TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname, version);
02183       if (sqlinfo==0) return kColUnknown;
02184 
02185       // this will indicate that streamer is completely custom
02186       if (sqlinfo->IsClassTableExist()) {
02187          data->AddUnpackInt(sqlio::Version, version);
02188       } else {
02189          TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo);
02190          if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown;
02191          AddObjectData(objdata);
02192       }
02193 
02194       break;
02195    }
02196 
02197       // This is a case when streamer of object will be called directly.
02198       // Typically it happens when object is data memeber of the class.
02199       // Here we need to define class of object and if it was written by
02200       // normal streamer (via TStreamerInfo methods) or directly as blob.
02201       // When blob was used, blob data should be readed.
02202       // In normal case only version is required. Other object data will be
02203       // read by TBufferSQL2::IncrementLevel method
02204    case kColObject: {
02205       located = data->LocateColumn(colname.Data());
02206       if (located==kColUnknown) return located;
02207 
02208       const char* strobjid = data->GetValue();
02209       if (strobjid==0) return kColUnknown;
02210 
02211       Long64_t objid = sqlio::atol64(strobjid);
02212 
02213       // when nothing was stored, nothing need to be read. skip
02214       if (objid<0) break;
02215 
02216       TString clname;
02217       Version_t version;
02218 
02219       if (!buf->SqlObjectInfo(objid, clname, version)) return kColUnknown;
02220 
02221       // special treatment for TObject
02222       if (clname==TObject::Class()->GetName()) {
02223          UnpackTObject(f, buf, data, objid, version);
02224          break;
02225       }
02226 
02227       TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname.Data(), version);
02228       if (sqlinfo==0) return kColUnknown;
02229 
02230       if (sqlinfo->IsClassTableExist()) {
02231          data->AddUnpackInt(sqlio::Version, version);
02232       } else {
02233          TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo);
02234          if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown;
02235          AddObjectData(objdata);
02236       }
02237 
02238       // work around to store objid of object, which is memeber of class
02239       fValue = strobjid;
02240 
02241       break;
02242    }
02243 
02244       // this is case of pointer on any object
02245       // field contains objectid.
02246       // Object id, class of object and so on will be checked
02247       // when TBuffer::ReadObject method will be called
02248    case kColObjectPtr: {
02249       located = data->LocateColumn(colname.Data());
02250       break;
02251    }
02252 
02253    // this is case of on object which is treated normally in TBuffer
02254    // field should contains objectid.
02255    // Object id, class of object and so on will be checked
02256    // when TBuffer::StreamObject method will be called
02257    case kColNormObject: {
02258       located = data->LocateColumn(colname.Data());
02259       break;
02260    }
02261 
02262    case kColNormObjectArray: {
02263       located = data->LocateColumn(colname.Data());
02264       break;
02265    }
02266 
02267    case kColTString: {
02268       located = data->LocateColumn(colname);
02269       if (located==kColUnknown) return located;
02270       const char* value = data->GetValue();
02271 
02272       Long64_t objid = DefineObjectId(kTRUE);
02273       Int_t strid = f->IsLongStringCode(objid, value);
02274 
02275       TString buf2;
02276 
02277       // if special prefix found, than try get such string
02278       if (strid>0)
02279          if (f->GetLongString(objid, strid, buf2))
02280             value = buf2.Data();
02281 
02282       Int_t len = (value==0) ? 0 : strlen(value);
02283       if (len<255) {
02284          data->AddUnpackInt(sqlio::UChar, len);
02285       } else {
02286          data->AddUnpackInt(sqlio::UChar, 255);
02287          data->AddUnpackInt(sqlio::Int, len);
02288       }
02289       if (len>0)
02290          data->AddUnpack(sqlio::CharStar, value);
02291       break;
02292    }
02293 
02294    case kColRawData: {
02295       located = data->LocateColumn(colname.Data(), kTRUE);
02296       break;
02297    }
02298 
02299    case kColObjectArray: {
02300       located = data->LocateColumn(colname.Data(), kTRUE);
02301       break;
02302    }
02303    }
02304 
02305    if (!located) coltype = kColUnknown;
02306 
02307    return coltype;
02308 }
02309 
02310 //________________________________________________________________________
02311 Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion)
02312 {
02313    // Unpack TObject data in form, understodable by custom TObject streamer
02314 
02315    TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TObject::Class()->GetName(), clversion);
02316    if (sqlinfo==0) return kFALSE;
02317 
02318    TSQLObjectData* tobjdata = buf->SqlObjectData(objid, sqlinfo);
02319    if (tobjdata==0) return kFALSE;
02320 
02321    data->AddUnpackInt(sqlio::Version, clversion);
02322 
02323    tobjdata->LocateColumn(sqlio::TObjectUniqueId);
02324    data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
02325    tobjdata->ShiftToNextValue();
02326 
02327    tobjdata->LocateColumn(sqlio::TObjectBits);
02328    data->AddUnpack(sqlio::UInt, tobjdata->GetValue());
02329    tobjdata->ShiftToNextValue();
02330 
02331    tobjdata->LocateColumn(sqlio::TObjectProcessId);
02332    const char* value = tobjdata->GetValue();
02333    if ((value!=0) && (strlen(value)>0))
02334       data->AddUnpack(sqlio::UShort, value);
02335 
02336    delete tobjdata;
02337 
02338    return kTRUE;
02339 }
02340 
02341 //________________________________________________________________________
02342 Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion)
02343 {
02344    // Unpack TString data in form, understodable by custom TString streamer
02345 
02346    TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TString::Class()->GetName(), clversion);
02347    if (sqlinfo==0) return kFALSE;
02348 
02349    TSQLObjectData* tstringdata = buf->SqlObjectData(objid, sqlinfo);
02350    if (tstringdata==0) return kFALSE;
02351 
02352    tstringdata->LocateColumn(sqlio::TStringValue);
02353 
02354    const char* value = tstringdata->GetValue();
02355 
02356    Int_t len = (value==0) ? 0 : strlen(value);
02357    if (len<255) {
02358       data->AddUnpackInt(sqlio::UChar, len);
02359    } else {
02360       data->AddUnpackInt(sqlio::UChar, 255);
02361       data->AddUnpackInt(sqlio::Int, len);
02362    }
02363    if (len>0)
02364       data->AddUnpack(sqlio::CharStar, value);
02365 
02366    delete tstringdata;
02367 
02368    return kTRUE;
02369 }
02370 
02371 //________________________________________________________________________
02372 void TSQLStructure::AddStrBrackets(TString &s, const char* quote)
02373 {
02374    // adds quotes arround string value and replaces some special symbols
02375    if (strcmp(quote,"\"")==0) s.ReplaceAll("\"","\\\"");
02376                         else  s.ReplaceAll("'","''");
02377    s.Prepend(quote);
02378    s.Append(quote);
02379 }

Generated on Tue Jul 5 14:30:33 2011 for ROOT_528-00b_version by  doxygen 1.5.1