From 186aa6e8a116cca6346f01a10b385a3452b97f01 Mon Sep 17 00:00:00 2001 From: Philippe Canal <pcanal@fnal.gov> Date: Wed, 1 Feb 2006 18:57:41 +0000 Subject: [PATCH] From Sergei Linev: Move CreateKey from TDirectory to TFile Here is also optimisation of SQL statements and adjustement for Oracle. Implementation of ClassBegin()/ClassMember()/ClassEnd() methdos for TBufferSQL2 and TBufferXML. I also implementation for ClassMemeber() method for case of "raw:data" for SQL and XML cases. git-svn-id: http://root.cern.ch/svn/root/trunk@13977 27541ba8-7e3a-0410-8455-c3a389f83636 --- sql/inc/LinkDef.h | 4 +- sql/inc/TBufferSQL2.h | 483 ++++++++++++++-------------- sql/inc/TKeySQL.h | 34 +- sql/inc/TSQLFile.h | 45 +-- sql/inc/TSQLObjectData.h | 61 +++- sql/inc/TSQLStructure.h | 46 ++- sql/src/TBufferSQL2.cxx | 595 +++++++++++++++++++++++++--------- sql/src/TKeySQL.cxx | 207 ++++++------ sql/src/TSQLFile.cxx | 590 ++++++++++++++++++++++++---------- sql/src/TSQLObjectData.cxx | 117 ++++++- sql/src/TSQLStructure.cxx | 631 ++++++++++++++++++++++--------------- xml/inc/TKeyXML.h | 22 +- xml/inc/TXMLFile.h | 7 +- xml/src/TBufferXML.cxx | 12 +- xml/src/TKeyXML.cxx | 173 +++++----- xml/src/TXMLFile.cxx | 13 +- 16 files changed, 1935 insertions(+), 1105 deletions(-) diff --git a/sql/inc/LinkDef.h b/sql/inc/LinkDef.h index 2fdff4be94e..d7450200d0a 100644 --- a/sql/inc/LinkDef.h +++ b/sql/inc/LinkDef.h @@ -1,4 +1,4 @@ -/* @(#)root/sql:$Name: $:$Id: LinkDef.h,v 1.1 2005/12/07 14:49:24 rdm Exp $ */ +/* @(#)root/sql:$Name: $:$Id: LinkDef.h,v 1.2 2005/12/07 14:59:57 rdm Exp $ */ /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * @@ -14,7 +14,9 @@ #pragma link C++ class TBufferSQL2; #pragma link C++ class TKeySQL; #pragma link C++ class TSQLClassInfo; +#pragma link C++ class TSQLObjectInfo; #pragma link C++ class TSQLObjectData; +#pragma link C++ class TSQLObjectDataPool; #pragma link C++ class TSQLStructure; #pragma link C++ class TSQLColumnData; diff --git a/sql/inc/TBufferSQL2.h b/sql/inc/TBufferSQL2.h index e7c8c5014b8..e09bf2a7cfe 100644 --- a/sql/inc/TBufferSQL2.h +++ b/sql/inc/TBufferSQL2.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TBufferSQL2.h,v 1.6 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TBufferSQL2.h,v 1.7 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 20/11/2005 @@ -26,6 +26,7 @@ #include "TObjArray.h" #endif +class TMap; class TExMap; class TStreamerInfo; class TStreamerElement; @@ -39,245 +40,255 @@ class TSQLRow; class TSQLFile; class TSQLStructure; class TSQLObjectData; +class TSQLClassInfo; class TBufferSQL2 : public TBuffer { - protected: - - TSQLFile* fSQL; //! instance of TSQLFile - TSQLStructure* fStructure; //! structures, created by object storing - TSQLStructure* fStk; //! pointer on current active structure (stack head) - TExMap* fObjMap; //! Map between stored objects and object id - TObjArray* fIdArray; //! List of used objects ids - TString fReadBuffer; //! Buffer for read value - Int_t fErrorFlag; //! Error id value - Bool_t fExpectedChain; //! flag to resolve situation when several elements of same basic type stored as FastArray - Int_t fCompressLevel; //! compress level used to minimize size of data in database - Int_t fReadVersionBuffer; //! buffer, used to by ReadVersion method - Int_t fObjIdCounter; //! counter of objects id - Bool_t fIgnoreVerification; //! ignore verification of names - TSQLObjectData* fCurrentData; //! - - // TBufferSQL2 objects cannot be copied or assigned - TBufferSQL2(const TBufferSQL2 &); // not implemented - void operator=(const TBufferSQL2 &); // not implemented - - TBufferSQL2(); - - // redefined protected virtual functions - - virtual void WriteObject(const void *actualObjStart, const TClass *actualClass); - - // end redefined protected virtual functions - - TSQLStructure* PushStack(); - TSQLStructure* PopStack(); - TSQLStructure* Stack(Int_t depth = 0); - - Bool_t ProcessPointer(const void* ptr, Int_t& objid); - void RegisterPointer(const void* ptr, Int_t objid); - - void WorkWithElement(TStreamerElement* elem, Int_t number); - - Int_t SqlReadArraySize(); - - Bool_t SqlWriteBasic(Char_t value); - Bool_t SqlWriteBasic(Short_t value); - Bool_t SqlWriteBasic(Int_t value); - Bool_t SqlWriteBasic(Long_t value); - Bool_t SqlWriteBasic(Long64_t value); - Bool_t SqlWriteBasic(Float_t value); - Bool_t SqlWriteBasic(Double_t value); - Bool_t SqlWriteBasic(Bool_t value); - Bool_t SqlWriteBasic(UChar_t value); - Bool_t SqlWriteBasic(UShort_t value); - Bool_t SqlWriteBasic(UInt_t value); - Bool_t SqlWriteBasic(ULong_t value); - Bool_t SqlWriteBasic(ULong64_t value); - Bool_t SqlWriteValue(const char* value, const char* tname); - - void SqlReadBasic(Char_t& value); - void SqlReadBasic(Short_t& value); - void SqlReadBasic(Int_t& value); - void SqlReadBasic(Long_t& value); - void SqlReadBasic(Long64_t& value); - void SqlReadBasic(Float_t& value); - void SqlReadBasic(Double_t& value); - void SqlReadBasic(Bool_t& value); - void SqlReadBasic(UChar_t& value); - void SqlReadBasic(UShort_t& value); - void SqlReadBasic(UInt_t& value); - void SqlReadBasic(ULong_t& value); - void SqlReadBasic(ULong64_t& value); - const char* SqlReadValue(const char* tname); - const char* SqlReadCharStarValue(); - - Int_t SqlWriteObject(const void* obj, const TClass* objClass, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); - void* SqlReadObject(void* obj, TClass** cl = 0, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); - void* SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); + +friend class TSQLStructure; - public: +protected: + + TSQLFile* fSQL; //! instance of TSQLFile + TSQLStructure* fStructure; //! structures, created by object storing + TSQLStructure* fStk; //! pointer on current active structure (stack head) + TExMap* fObjMap; //! Map between stored objects and object id + TString fReadBuffer; //! Buffer for read value + Int_t fErrorFlag; //! Error id value + Bool_t fExpectedChain; //! flag to resolve situation when several elements of same basic type stored as FastArray + Int_t fCompressLevel; //! compress level used to minimize size of data in database + Int_t fReadVersionBuffer; //! buffer, used to by ReadVersion method + Long64_t fObjIdCounter; //! counter of objects id + Bool_t fIgnoreVerification; //! ignore verification of names + TSQLObjectData* fCurrentData; //! + TObjArray* fObjectsInfos; //! array of objects info for selected key + Long64_t fFirstObjId; //! id of first object to be read from the database + Long64_t fLastObjId; //! id of last object correspond to this key + TMap* fPoolsMap; //! map of pools with data from different tables + + // TBufferSQL2 objects cannot be copied or assigned + TBufferSQL2(const TBufferSQL2 &); // not implemented + void operator=(const TBufferSQL2 &); // not implemented + + TBufferSQL2(); + + // redefined protected virtual functions + + virtual void WriteObject(const void *actualObjStart, const TClass *actualClass); + + // end redefined protected virtual functions + + TSQLStructure* PushStack(); + TSQLStructure* PopStack(); + TSQLStructure* Stack(Int_t depth = 0); + + void WorkWithClass(const char* classname, Version_t classversion); + void WorkWithElement(TStreamerElement* elem, Int_t number); + + Int_t SqlReadArraySize(); + Bool_t SqlObjectInfo(Long64_t objid, TString& clname, Version_t& version); + TSQLObjectData* SqlObjectData(Long64_t objid, TSQLClassInfo* sqlinfo); + + Bool_t SqlWriteBasic(Char_t value); + Bool_t SqlWriteBasic(Short_t value); + Bool_t SqlWriteBasic(Int_t value); + Bool_t SqlWriteBasic(Long_t value); + Bool_t SqlWriteBasic(Long64_t value); + Bool_t SqlWriteBasic(Float_t value); + Bool_t SqlWriteBasic(Double_t value); + Bool_t SqlWriteBasic(Bool_t value); + Bool_t SqlWriteBasic(UChar_t value); + Bool_t SqlWriteBasic(UShort_t value); + Bool_t SqlWriteBasic(UInt_t value); + Bool_t SqlWriteBasic(ULong_t value); + Bool_t SqlWriteBasic(ULong64_t value); + Bool_t SqlWriteValue(const char* value, const char* tname); + + void SqlReadBasic(Char_t& value); + void SqlReadBasic(Short_t& value); + void SqlReadBasic(Int_t& value); + void SqlReadBasic(Long_t& value); + void SqlReadBasic(Long64_t& value); + void SqlReadBasic(Float_t& value); + void SqlReadBasic(Double_t& value); + void SqlReadBasic(Bool_t& value); + void SqlReadBasic(UChar_t& value); + void SqlReadBasic(UShort_t& value); + void SqlReadBasic(UInt_t& value); + void SqlReadBasic(ULong_t& value); + void SqlReadBasic(ULong64_t& value); + const char* SqlReadValue(const char* tname); + const char* SqlReadCharStarValue(); + + Int_t SqlWriteObject(const void* obj, const TClass* objClass, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); + void* SqlReadObject(void* obj, TClass** cl = 0, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); + void* SqlReadObjectDirect(void* obj, TClass** cl, Long64_t objid, TMemberStreamer *streamer = 0, Int_t streamer_index = 0); + +public: + + TBufferSQL2(TBuffer::EMode mode); + TBufferSQL2(TBuffer::EMode mode, TSQLFile* file); + virtual ~TBufferSQL2(); + + void SetCompressionLevel(int level) { fCompressLevel = level; } + + TSQLStructure* GetStructure() const { return fStructure; } + + Int_t GetErrorFlag() const { return fErrorFlag; } + + void SetIgnoreVerification() { fIgnoreVerification = kTRUE; } + + TSQLStructure* SqlWriteAny(const void* obj, const TClass* cl, Long64_t objid); + + void* SqlReadAny(Long64_t keyid, Long64_t objid, TClass** cl, void* obj = 0); + + // suppress class writing/reading + + virtual TClass* ReadClass(const TClass* cl = 0, UInt_t* objTag = 0); + virtual void WriteClass(const TClass* cl); + + // redefined virtual functions of TBuffer + + virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss); // SL + virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *classname); // SL + virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion = kFALSE); // SL + + virtual Version_t ReadVersion(UInt_t *start = 0, UInt_t *bcnt = 0, const TClass *cl = 0); // SL + virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt = kFALSE); // SL + + virtual void* ReadObjectAny(const TClass* clCast); + virtual void SkipObjectAny(); + + virtual void IncrementLevel(TStreamerInfo*); + virtual void SetStreamerElementNumber(Int_t); + virtual void DecrementLevel(TStreamerInfo*); - TBufferSQL2(TBuffer::EMode mode); - TBufferSQL2(TBuffer::EMode mode, TSQLFile* file); - virtual ~TBufferSQL2(); - - void SetCompressionLevel(int level) { fCompressLevel = level; } - - TSQLStructure* GetStructure() const { return fStructure; } - - Int_t GetErrorFlag() const { return fErrorFlag; } - - void SetIgnoreVerification() { fIgnoreVerification = kTRUE; } - - TSQLStructure* SqlWrite(const TObject* obj, Int_t objid); - TSQLStructure* SqlWrite(const void* obj, const TClass* cl, Int_t objid); - - void* SqlReadAny(Int_t objid, void* obj, TClass** cl); - - // suppress class writing/reading - - virtual TClass* ReadClass(const TClass* cl = 0, UInt_t* objTag = 0); - virtual void WriteClass(const TClass* cl); - - // redefined virtual functions of TBuffer - - virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss); // SL - virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *classname); // SL - virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion = kFALSE); // SL - - virtual Version_t ReadVersion(UInt_t *start = 0, UInt_t *bcnt = 0, const TClass *cl = 0); // SL - virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt = kFALSE); // SL - - virtual void* ReadObjectAny(const TClass* clCast); - virtual void SkipObjectAny(); - - virtual void IncrementLevel(TStreamerInfo*); - virtual void SetStreamerElementNumber(Int_t); - virtual void DecrementLevel(TStreamerInfo*); - - virtual void WriteObject(const TObject *obj); - - virtual void ReadDouble32 (Double_t *d, TStreamerElement *ele=0); - virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=0); - - virtual Int_t ReadArray(Bool_t *&b); - virtual Int_t ReadArray(Char_t *&c); - virtual Int_t ReadArray(UChar_t *&c); - virtual Int_t ReadArray(Short_t *&h); - virtual Int_t ReadArray(UShort_t *&h); - virtual Int_t ReadArray(Int_t *&i); - virtual Int_t ReadArray(UInt_t *&i); - virtual Int_t ReadArray(Long_t *&l); - virtual Int_t ReadArray(ULong_t *&l); - virtual Int_t ReadArray(Long64_t *&l); - virtual Int_t ReadArray(ULong64_t *&l); - virtual Int_t ReadArray(Float_t *&f); - virtual Int_t ReadArray(Double_t *&d); - virtual Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=0); - - virtual Int_t ReadStaticArray(Bool_t *b); - virtual Int_t ReadStaticArray(Char_t *c); - virtual Int_t ReadStaticArray(UChar_t *c); - virtual Int_t ReadStaticArray(Short_t *h); - virtual Int_t ReadStaticArray(UShort_t *h); - virtual Int_t ReadStaticArray(Int_t *i); - virtual Int_t ReadStaticArray(UInt_t *i); - virtual Int_t ReadStaticArray(Long_t *l); - virtual Int_t ReadStaticArray(ULong_t *l); - virtual Int_t ReadStaticArray(Long64_t *l); - virtual Int_t ReadStaticArray(ULong64_t *l); - virtual Int_t ReadStaticArray(Float_t *f); - virtual Int_t ReadStaticArray(Double_t *d); - virtual Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=0); - - virtual void ReadFastArray(Bool_t *b, Int_t n); - virtual void ReadFastArray(Char_t *c, Int_t n); - virtual void ReadFastArray(UChar_t *c, Int_t n); - virtual void ReadFastArray(Short_t *h, Int_t n); - virtual void ReadFastArray(UShort_t *h, Int_t n); - virtual void ReadFastArray(Int_t *i, Int_t n); - virtual void ReadFastArray(UInt_t *i, Int_t n); - virtual void ReadFastArray(Long_t *l, Int_t n); - virtual void ReadFastArray(ULong_t *l, Int_t n); - virtual void ReadFastArray(Long64_t *l, Int_t n); - virtual void ReadFastArray(ULong64_t *l, Int_t n); - virtual void ReadFastArray(Float_t *f, Int_t n); - virtual void ReadFastArray(Double_t *d, Int_t n); - virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0); - - virtual void WriteArray(const Bool_t *b, Int_t n); - virtual void WriteArray(const Char_t *c, Int_t n); - virtual void WriteArray(const UChar_t *c, Int_t n); - virtual void WriteArray(const Short_t *h, Int_t n); - virtual void WriteArray(const UShort_t *h, Int_t n); - virtual void WriteArray(const Int_t *i, Int_t n); - virtual void WriteArray(const UInt_t *i, Int_t n); - virtual void WriteArray(const Long_t *l, Int_t n); - virtual void WriteArray(const ULong_t *l, Int_t n); - virtual void WriteArray(const Long64_t *l, Int_t n); - virtual void WriteArray(const ULong64_t *l, Int_t n); - virtual void WriteArray(const Float_t *f, Int_t n); - virtual void WriteArray(const Double_t *d, Int_t n); - virtual void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0); - virtual void ReadFastArray(void *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0); - virtual void ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0); - - virtual void WriteFastArray(const Bool_t *b, Int_t n); - virtual void WriteFastArray(const Char_t *c, Int_t n); - virtual void WriteFastArray(const UChar_t *c, Int_t n); - virtual void WriteFastArray(const Short_t *h, Int_t n); - virtual void WriteFastArray(const UShort_t *h, Int_t n); - virtual void WriteFastArray(const Int_t *i, Int_t n); - virtual void WriteFastArray(const UInt_t *i, Int_t n); - virtual void WriteFastArray(const Long_t *l, Int_t n); - virtual void WriteFastArray(const ULong_t *l, Int_t n); - virtual void WriteFastArray(const Long64_t *l, Int_t n); - virtual void WriteFastArray(const ULong64_t *l, Int_t n); - virtual void WriteFastArray(const Float_t *f, Int_t n); - virtual void WriteFastArray(const Double_t *d, Int_t n); - virtual void WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0); - virtual void WriteFastArray(void *start, const TClass *cl, Int_t n=1, TMemberStreamer *s=0); - virtual Int_t WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0); - - virtual void StreamObject(void *obj, const type_info &typeinfo); - virtual void StreamObject(void *obj, const char *className); - virtual void StreamObject(void *obj, const TClass *cl); - virtual void StreamObject(TObject *obj); - virtual void StreamObject(void *obj, TMemberStreamer *streamer, const TClass *cl, Int_t n = 0); - - virtual TBuffer &operator>>(Bool_t &b); - virtual TBuffer &operator>>(Char_t &c); - virtual TBuffer &operator>>(UChar_t &c); - virtual TBuffer &operator>>(Short_t &h); - virtual TBuffer &operator>>(UShort_t &h); - virtual TBuffer &operator>>(Int_t &i); - virtual TBuffer &operator>>(UInt_t &i); - virtual TBuffer &operator>>(Long_t &l); - virtual TBuffer &operator>>(ULong_t &l); - virtual TBuffer &operator>>(Long64_t &l); - virtual TBuffer &operator>>(ULong64_t &l); - virtual TBuffer &operator>>(Float_t &f); - virtual TBuffer &operator>>(Double_t &d); - virtual TBuffer &operator>>(Char_t *c); - - virtual TBuffer &operator<<(Bool_t b); - virtual TBuffer &operator<<(Char_t c); - virtual TBuffer &operator<<(UChar_t c); - virtual TBuffer &operator<<(Short_t h); - virtual TBuffer &operator<<(UShort_t h); - virtual TBuffer &operator<<(Int_t i); - virtual TBuffer &operator<<(UInt_t i); - virtual TBuffer &operator<<(Long_t l); - virtual TBuffer &operator<<(ULong_t l); - virtual TBuffer &operator<<(Long64_t l); - virtual TBuffer &operator<<(ULong64_t l); - virtual TBuffer &operator<<(Float_t f); - virtual TBuffer &operator<<(Double_t d); - virtual TBuffer &operator<<(const Char_t *c); - - // end of redefined virtual functions - - ClassDef(TBufferSQL2,1); //a specialized TBuffer to convert data to SQL statements or read data from SQL tables + virtual void ClassBegin(const TClass*, Version_t = -1); + virtual void ClassEnd(const TClass*); + virtual void ClassMember(const char* name, const char* typeName = 0, Int_t arrsize1 = -1, Int_t arrsize2 = -1); + + virtual void WriteObject(const TObject *obj); + + virtual void ReadDouble32 (Double_t *d, TStreamerElement *ele=0); + virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=0); + + virtual Int_t ReadArray(Bool_t *&b); + virtual Int_t ReadArray(Char_t *&c); + virtual Int_t ReadArray(UChar_t *&c); + virtual Int_t ReadArray(Short_t *&h); + virtual Int_t ReadArray(UShort_t *&h); + virtual Int_t ReadArray(Int_t *&i); + virtual Int_t ReadArray(UInt_t *&i); + virtual Int_t ReadArray(Long_t *&l); + virtual Int_t ReadArray(ULong_t *&l); + virtual Int_t ReadArray(Long64_t *&l); + virtual Int_t ReadArray(ULong64_t *&l); + virtual Int_t ReadArray(Float_t *&f); + virtual Int_t ReadArray(Double_t *&d); + virtual Int_t ReadArrayDouble32(Double_t *&d, TStreamerElement *ele=0); + + virtual Int_t ReadStaticArray(Bool_t *b); + virtual Int_t ReadStaticArray(Char_t *c); + virtual Int_t ReadStaticArray(UChar_t *c); + virtual Int_t ReadStaticArray(Short_t *h); + virtual Int_t ReadStaticArray(UShort_t *h); + virtual Int_t ReadStaticArray(Int_t *i); + virtual Int_t ReadStaticArray(UInt_t *i); + virtual Int_t ReadStaticArray(Long_t *l); + virtual Int_t ReadStaticArray(ULong_t *l); + virtual Int_t ReadStaticArray(Long64_t *l); + virtual Int_t ReadStaticArray(ULong64_t *l); + virtual Int_t ReadStaticArray(Float_t *f); + virtual Int_t ReadStaticArray(Double_t *d); + virtual Int_t ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele=0); + + virtual void ReadFastArray(Bool_t *b, Int_t n); + virtual void ReadFastArray(Char_t *c, Int_t n); + virtual void ReadFastArray(UChar_t *c, Int_t n); + virtual void ReadFastArray(Short_t *h, Int_t n); + virtual void ReadFastArray(UShort_t *h, Int_t n); + virtual void ReadFastArray(Int_t *i, Int_t n); + virtual void ReadFastArray(UInt_t *i, Int_t n); + virtual void ReadFastArray(Long_t *l, Int_t n); + virtual void ReadFastArray(ULong_t *l, Int_t n); + virtual void ReadFastArray(Long64_t *l, Int_t n); + virtual void ReadFastArray(ULong64_t *l, Int_t n); + virtual void ReadFastArray(Float_t *f, Int_t n); + virtual void ReadFastArray(Double_t *d, Int_t n); + virtual void ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele=0); + + virtual void WriteArray(const Bool_t *b, Int_t n); + virtual void WriteArray(const Char_t *c, Int_t n); + virtual void WriteArray(const UChar_t *c, Int_t n); + virtual void WriteArray(const Short_t *h, Int_t n); + virtual void WriteArray(const UShort_t *h, Int_t n); + virtual void WriteArray(const Int_t *i, Int_t n); + virtual void WriteArray(const UInt_t *i, Int_t n); + virtual void WriteArray(const Long_t *l, Int_t n); + virtual void WriteArray(const ULong_t *l, Int_t n); + virtual void WriteArray(const Long64_t *l, Int_t n); + virtual void WriteArray(const ULong64_t *l, Int_t n); + virtual void WriteArray(const Float_t *f, Int_t n); + virtual void WriteArray(const Double_t *d, Int_t n); + virtual void WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0); + virtual void ReadFastArray(void *start , const TClass *cl, Int_t n=1, TMemberStreamer *s=0); + virtual void ReadFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0); + + virtual void WriteFastArray(const Bool_t *b, Int_t n); + virtual void WriteFastArray(const Char_t *c, Int_t n); + virtual void WriteFastArray(const UChar_t *c, Int_t n); + virtual void WriteFastArray(const Short_t *h, Int_t n); + virtual void WriteFastArray(const UShort_t *h, Int_t n); + virtual void WriteFastArray(const Int_t *i, Int_t n); + virtual void WriteFastArray(const UInt_t *i, Int_t n); + virtual void WriteFastArray(const Long_t *l, Int_t n); + virtual void WriteFastArray(const ULong_t *l, Int_t n); + virtual void WriteFastArray(const Long64_t *l, Int_t n); + virtual void WriteFastArray(const ULong64_t *l, Int_t n); + virtual void WriteFastArray(const Float_t *f, Int_t n); + virtual void WriteFastArray(const Double_t *d, Int_t n); + virtual void WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele=0); + virtual void WriteFastArray(void *start, const TClass *cl, Int_t n=1, TMemberStreamer *s=0); + virtual Int_t WriteFastArray(void **startp, const TClass *cl, Int_t n=1, Bool_t isPreAlloc=kFALSE, TMemberStreamer *s=0); + + virtual void StreamObject(void *obj, const type_info &typeinfo); + virtual void StreamObject(void *obj, const char *className); + virtual void StreamObject(void *obj, const TClass *cl); + virtual void StreamObject(TObject *obj); + virtual void StreamObject(void *obj, TMemberStreamer *streamer, const TClass *cl, Int_t n = 0); + + virtual TBuffer &operator>>(Bool_t &b); + virtual TBuffer &operator>>(Char_t &c); + virtual TBuffer &operator>>(UChar_t &c); + virtual TBuffer &operator>>(Short_t &h); + virtual TBuffer &operator>>(UShort_t &h); + virtual TBuffer &operator>>(Int_t &i); + virtual TBuffer &operator>>(UInt_t &i); + virtual TBuffer &operator>>(Long_t &l); + virtual TBuffer &operator>>(ULong_t &l); + virtual TBuffer &operator>>(Long64_t &l); + virtual TBuffer &operator>>(ULong64_t &l); + virtual TBuffer &operator>>(Float_t &f); + virtual TBuffer &operator>>(Double_t &d); + virtual TBuffer &operator>>(Char_t *c); + + virtual TBuffer &operator<<(Bool_t b); + virtual TBuffer &operator<<(Char_t c); + virtual TBuffer &operator<<(UChar_t c); + virtual TBuffer &operator<<(Short_t h); + virtual TBuffer &operator<<(UShort_t h); + virtual TBuffer &operator<<(Int_t i); + virtual TBuffer &operator<<(UInt_t i); + virtual TBuffer &operator<<(Long_t l); + virtual TBuffer &operator<<(ULong_t l); + virtual TBuffer &operator<<(Long64_t l); + virtual TBuffer &operator<<(ULong64_t l); + virtual TBuffer &operator<<(Float_t f); + virtual TBuffer &operator<<(Double_t d); + virtual TBuffer &operator<<(const Char_t *c); + + // end of redefined virtual functions + +ClassDef(TBufferSQL2,1); //a specialized TBuffer to convert data to SQL statements or read data from SQL tables }; #endif diff --git a/sql/inc/TKeySQL.h b/sql/inc/TKeySQL.h index 492f532238a..237a2fd699d 100644 --- a/sql/inc/TKeySQL.h +++ b/sql/inc/TKeySQL.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TKeySQL.h,v 1.3 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TKeySQL.h,v 1.4 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -33,33 +33,33 @@ protected: TKeySQL(); virtual Int_t Read(const char *name) { return TKey::Read(name); } - void StoreObject(const void* obj, const TClass* cl); - void* SqlReadAny(void* obj, const TClass* expectedClass); + void StoreKeyObject(const void* obj, const TClass* cl); + void* ReadKeyObject(void* obj, const TClass* expectedClass); - TSQLFile* fFile; //! pointer on SQL file - Int_t fKeyId; //! key identifier in KeysTables - Int_t fDirId; //! parent directory identifier - Int_t fObjId; //! stored object identifer + Long64_t fKeyId; //! key identifier in KeysTables + Long64_t fObjId; //! stored object identifer public: - TKeySQL(TSQLFile* file, const TObject* obj, const char* name); - TKeySQL(TSQLFile* file, const void* obj, const TClass* cl, const char* name); - TKeySQL(TSQLFile* file, Int_t keyid, Int_t dirid, Int_t objid, const char* name, + TKeySQL(TDirectory* mother, const TObject* obj, const char* name, const char* title = 0); + TKeySQL(TDirectory* mother, const void* obj, const TClass* cl, const char* name, const char* title = 0); + TKeySQL(TDirectory* mother, Long64_t keyid, Long64_t objid, + const char* name, const char* title, const char* keydatetime, Int_t cycle, const char* classname); virtual ~TKeySQL(); + + Bool_t IsKeyModified(const char* keyname, const char* keytitle, const char* keydatime, Int_t cycle, const char* classname); - Int_t GetDBKeyId() const { return fKeyId; } - Int_t GetDBDirId() const { return fDirId; } - Int_t GetDBObjId() const { return fObjId; } + Long64_t GetDBKeyId() const { return fKeyId; } + Long64_t GetDBObjId() const { return fObjId; } + Long64_t GetDBDirId() const; // redefined TKey Methods - virtual void Browse(TBrowser *b); virtual void Delete(Option_t *option=""); virtual void DeleteBuffer() {} virtual void FillBuffer(char *&) {} virtual char *GetBuffer() const { return 0; } - virtual Long64_t GetSeekKey() const { return 1; } - virtual Long64_t GetSeekPdir() const { return 1;} + virtual Long64_t GetSeekKey() const { return GetDBObjId() > 0 ? GetDBObjId() : 0; } + virtual Long64_t GetSeekPdir() const { return GetDBDirId() > 0 ? GetDBDirId() : 0; } virtual void Keep() {} virtual Int_t Read(TObject* obj); @@ -69,8 +69,6 @@ public: virtual void ReadBuffer(char *&) {} virtual void ReadFile() {} virtual void SetBuffer() { fBuffer = 0; } - virtual void SetParent(const TObject* ) { } - virtual Int_t Sizeof() const { return 0; } virtual Int_t WriteFile(Int_t =1, TFile* = 0) { return 0; } ClassDef(TKeySQL,1) // a special TKey for SQL data base diff --git a/sql/inc/TSQLFile.h b/sql/inc/TSQLFile.h index b77978caed6..46cd1852471 100644 --- a/sql/inc/TSQLFile.h +++ b/sql/inc/TSQLFile.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLFile.h,v 1.5 2005/11/29 05:29:15 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLFile.h,v 1.6 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -72,27 +72,25 @@ protected: Bool_t IsWriteAccess(); Bool_t IsReadAccess(); - // create key for provided objects - virtual TKey* CreateKey(const TObject* obj, const char* name, Int_t bufsize); - virtual TKey* CreateKey(const void* obj, const TClass* cl, const char* name, Int_t bufsize); - // generic sql functions TSQLResult* SQLQuery(const char* cmd, Int_t flag = 0, Bool_t* res = 0); Bool_t SQLApplyCommands(TObjArray* cmds); TObjArray* SQLTablesList(const char* searchtable = 0); Bool_t SQLTestTable(const char* tablename); TObjArray* SQLTableColumns(const char* tablename); - Int_t SQLMaximumValue(const char* tablename, const char* columnname); + Long64_t SQLMaximumValue(const char* tablename, const char* columnname); void SQLDeleteAllTables(); Bool_t SQLStartTransaction(); Bool_t SQLCommit(); Bool_t SQLRollback(); // operation with keys structures in database - void DeleteKeyFromDB(Int_t keyid); - Bool_t WriteKeyData(Int_t keyid, Int_t dirid, Int_t objid, const char* name, const char* datime, Int_t cycle, const char* clname); - Int_t DefineNextKeyId(); - Bool_t ReadKeysForDirectory(TDirectory* dir, Int_t dir_id); + void DeleteKeyFromDB(Long64_t keyid); + Bool_t WriteKeyData(TKeySQL* key); + Bool_t UpdateKeyData(TKeySQL* key); + TKeySQL* FindSQLKey(TDirectory* dir, Long64_t keyid); + Long64_t DefineNextKeyId(); + Int_t StreamKeysForDirectory(TDirectory* dir, Bool_t doupdate, Long64_t specialkeyid = -1, TKeySQL** specialkey = 0); // handling SQL class info structures TSQLClassInfo* FindSQLClassInfo(const char* clname, Int_t version); @@ -102,17 +100,22 @@ protected: Bool_t ProduceClassSelectQuery(TStreamerInfo* info, TSQLClassInfo* sqlinfo, TString& columns, TString& tables, Int_t& tablecnt); // operations with long string table - TString CodeLongString(Int_t objid, Int_t strid); - Int_t IsLongStringCode(const char* value, Int_t objid); + TString CodeLongString(Long64_t objid, Int_t strid); + Int_t IsLongStringCode(Long64_t objid, const char* value); Bool_t VerifyLongStringTable(); - Bool_t GetLongString(Int_t objid, Int_t strid, TString& value); + Bool_t GetLongString(Long64_t objid, Int_t strid, TString& value); // operation with object tables in database - Int_t VerifyObjectTable(); - TString SetObjectDataCmd(Int_t keyid, Int_t objid, TClass* cl); - Bool_t GetObjectData(Int_t objid, TString& clname, Version_t &version); - TSQLObjectData* GetObjectClassData(Int_t objid, TSQLClassInfo* sqlinfo); - void DeleteObjectFromTables(Int_t objid); + Long64_t VerifyObjectTable(); + Bool_t SQLObjectInfo(Long64_t objid, TString& clname, Version_t &version); + TObjArray* SQLObjectsInfo(Long64_t keyid); + TSQLResult* GetNormalClassData(Long64_t objid, TSQLClassInfo* sqlinfo); + TSQLResult* GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo* sqlinfo); + TSQLResult* GetBlobClassData(Long64_t objid, TSQLClassInfo* sqlinfo); + TSQLObjectData* GetObjectClassData(Long64_t objid, TSQLClassInfo* sqlinfo); + Long64_t StoreObjectInTables(Long64_t keyid, const void* obj, const TClass* cl); + Bool_t WriteSpecialObject(Long64_t keyid, TObject* obj, const char* name, const char* title); + TObject* ReadSpecialObject(Long64_t keyid, TObject* obj = 0); // sql specific types const char* SQLCompatibleType(Int_t typ) const; @@ -143,6 +146,7 @@ protected: Int_t fUseTransactions; //! use transaction statements for writing data into the tables Int_t fUseIndexes; //! use indexes for tables: 0 - off, 1 - only for basic tables, 2 + normal class tables, 3 - all tables Int_t fModifyCounter; //! indicates how many changes was done with database tables + Int_t fQuerisCounter; //! how many query was applied const char** fBasicTypes; //! pointer on list of basic types specific for currently connected SQL server const char** fOtherTypes; //! pointer on list of other SQL types like TEXT or blob @@ -186,6 +190,7 @@ public: Int_t GetUseTransactions() const { return fUseTransactions; } void SetUseIndexes(Int_t use_type = kIndexesBasic); Int_t GetUseIndexes() const { return fUseIndexes; } + Int_t GetQuerisCounter() const { return fQuerisCounter; } TString MakeSelectQuery(TClass* cl); Bool_t StartTransaction(); @@ -197,6 +202,8 @@ public: void StopLogFile(); // *MENU* virtual void Close(Option_t *option=""); // *MENU* + virtual TKey* CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize); + virtual TKey* CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize); virtual void DrawMap(const char* ="*",Option_t* ="") {} virtual void FillBuffer(char* &) {} virtual void Flush() {} @@ -237,7 +244,7 @@ public: virtual Int_t Write(const char* =0, Int_t=0, Int_t=0) { return 0; } virtual Int_t Write(const char* =0, Int_t=0, Int_t=0) const { return 0; } virtual void WriteFree() {} - virtual void WriteHeader() {} + virtual void WriteHeader(); virtual void WriteStreamerInfo(); ClassDef(TSQLFile,1) // ROOT TFile interface to SQL database diff --git a/sql/inc/TSQLObjectData.h b/sql/inc/TSQLObjectData.h index 50ea96a4708..fcc2192d158 100644 --- a/sql/inc/TSQLObjectData.h +++ b/sql/inc/TSQLObjectData.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLObjectData.h,v 1.3 2005/11/24 16:57:23 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLObjectData.h,v 1.4 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -29,23 +29,51 @@ #endif class TObjArray; +class TList; class TSQLClassInfo; class TSQLResult; class TSQLRow; + +class TSQLObjectInfo : public TObject { + +public: + + TSQLObjectInfo(); + TSQLObjectInfo(Long64_t objid, const char* classname, Version_t version); + virtual ~TSQLObjectInfo(); + + Long64_t GetObjId() const { return fObjId; } + const char* GetObjClassName() const { return fClassName.Data(); } + Version_t GetObjVersion() const { return fVersion; } + + +protected: + Long64_t fObjId; + TString fClassName; + Version_t fVersion; + +ClassDef(TSQLObjectInfo, 1); // Info (classname, version) about object in database + +}; + +//======================================================================= + class TSQLObjectData : public TObject { public: TSQLObjectData(); TSQLObjectData(TSQLClassInfo* sqlinfo, - Int_t objid, + Long64_t objid, TSQLResult* classdata, + TSQLRow* classrow, TSQLResult* blobdata); virtual ~TSQLObjectData(); - Int_t GetObjId() const { return fObjId; } + Long64_t GetObjId() const { return fObjId; } + TSQLClassInfo* GetInfo() const { return fInfo; } Bool_t LocateColumn(const char* colname, Bool_t isblob = kFALSE); Bool_t IsBlobData() const { return fCurrentBlob || (fUnpack!=0); } @@ -69,7 +97,8 @@ protected: const char* GetClassFieldName(Int_t n); TSQLClassInfo* fInfo; //! - Int_t fObjId; //! + Long64_t fObjId; //! + Bool_t fOwner; //! TSQLResult* fClassData; //! TSQLResult* fBlobData; //! Int_t fLocatedColumn; //! @@ -87,4 +116,28 @@ protected: }; +// ====================================================================== + +class TSQLObjectDataPool : public TObject { + +public: + TSQLObjectDataPool(); + TSQLObjectDataPool(TSQLClassInfo* info, TSQLResult* data); + virtual ~TSQLObjectDataPool(); + + TSQLClassInfo* GetSqlInfo() const { return fInfo; } + TSQLResult* GetClassData() const { return fClassData; } + TSQLRow* GetObjectRow(Long64_t objid); + +protected: + + TSQLClassInfo* fInfo; //! classinfo, for which pool is created + TSQLResult* fClassData; //! results with request to selected table + Bool_t fIsMoreRows; //! indicates if class data has not yet read rows + TList* fRowsPool; //! pool of extrcted, but didnot used rows + +ClassDef(TSQLObjectDataPool,1); + +}; + #endif diff --git a/sql/inc/TSQLStructure.h b/sql/inc/TSQLStructure.h index 4a0656e2e87..330350c0b03 100644 --- a/sql/inc/TSQLStructure.h +++ b/sql/inc/TSQLStructure.h @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLStructure.h,v 1.5 2005/12/01 16:30:43 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLStructure.h,v 1.6 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -39,6 +39,7 @@ class TStreamerElement; class TSQLFile; class TSqlRegistry; class TSQLObjectData; +class TBufferSQL2; class TSQLColumnData : public TObject { @@ -54,7 +55,7 @@ public: const char* value, Bool_t numeric); - TSQLColumnData(const char* name, Int_t value); + TSQLColumnData(const char* name, Long64_t value); virtual ~TSQLColumnData(); virtual const char* GetName() const { return fName.Data(); } @@ -72,9 +73,9 @@ protected: Bool_t CheckNormalClassPair(TSQLStructure* vers, TSQLStructure* info); - Int_t FindMaxRef(); + Long64_t FindMaxObjectId(); void PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const char* topname, Bool_t useblob = kFALSE); - Bool_t StoreObject(TSqlRegistry* reg, const char* objid, TClass* cl, Bool_t registerobj = kTRUE); + Bool_t StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl, Bool_t registerobj = kTRUE); Bool_t StoreObjectInNormalForm(TSqlRegistry* reg); Bool_t StoreClassInNormalForm(TSqlRegistry* reg); Bool_t StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* columns); @@ -107,12 +108,14 @@ public: Int_t GetType() const { return fType; } // this part requried for writing to SQL tables - void SetObjectRef(Int_t refid, const TClass* cl); - void SetObjectPointer(Int_t ptrid); + void SetObjectRef(Long64_t refid, const TClass* cl); + void SetObjectPointer(Long64_t ptrid); void SetVersion(const TClass* cl, Int_t version = -100); void SetClassStreamer(const TClass* cl); void SetStreamerInfo(const TStreamerInfo* info); void SetStreamerElement(const TStreamerElement* elem, Int_t number); + void SetCustomClass(const TClass* cl, Version_t version); + void SetCustomElement(TStreamerElement* elem); void SetValue(const char* value, const char* tname = 0); void SetArrayIndex(Int_t indx, Int_t cnt=1); void SetArray(Int_t sz = -1); @@ -123,6 +126,9 @@ public: TStreamerInfo* GetStreamerInfo() const; TStreamerElement* GetElement() const; Int_t GetElementNumber() const; + TClass* GetCustomClass() const; + Version_t GetCustomClassVersion() const; + Bool_t GetClassInfo(TClass* &cl, Version_t &version); const char* GetValueType() const; const char* GetValue() const; Int_t GetArrayIndex() const { return fArrayIndex; } @@ -135,8 +141,7 @@ public: // this is part specially for reading of sql tables - Int_t DefineObjectId(); - Bool_t IsClonesArray(); + Long64_t DefineObjectId(Bool_t recursive = kTRUE); void SetObjectData(TSQLObjectData* objdata); void AddObjectData(TSQLObjectData* objdata); @@ -145,17 +150,18 @@ public: virtual void Print(Option_t* option = "") const; void PrintLevel(Int_t level) const; - Bool_t ConvertToTables(TSQLFile* f, Int_t keyid, TObjArray* cmds); + Bool_t ConvertToTables(TSQLFile* f, Long64_t keyid, TObjArray* cmds); - Int_t LocateElementColumn(TSQLFile* f, TSQLObjectData* data); + Int_t LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data); - static Bool_t UnpackTObject(TSQLFile* f, TSQLObjectData* data, Int_t objid, Int_t clversion); - static Bool_t UnpackTString(TSQLFile* f, TSQLObjectData* data, Int_t objid, Int_t clversion); + static Bool_t UnpackTObject(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion); + static Bool_t UnpackTString(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion); static Bool_t IsNumericType(Int_t typ); static const char* GetSimpleTypeName(Int_t typ); static TString MakeArrayIndex(TStreamerElement* elem, Int_t n); static Int_t DefineElementColumnType(TStreamerElement* elem, TSQLFile* f); static TString DefineElementColumnName(TStreamerElement* elem, TSQLFile* f, Int_t indx = 0); + static void AddStrBrackets(TString &s, const char* quote); enum ESQLTypes { kSqlObject = 10001, @@ -166,7 +172,9 @@ public: kSqlElement = 10006, kSqlValue = 10007, kSqlArray = 10008, - kSqlObjectData = 10009 + kSqlObjectData = 10009, + kSqlCustomClass = 10010, + kSqlCustomElement= 10011 }; enum ESQLColumns { @@ -180,8 +188,7 @@ public: kColNormObjectArray = 7, kColObjectPtr = 8, kColTString = 9, - kColClonesArray = 10, - kColRawData = 11 + kColRawData = 10 }; ClassDef(TSQLStructure, 1); // Table/structure description used internally by YBufferSQL. @@ -190,8 +197,12 @@ public: // text constants, used in SQL I/O namespace sqlio { + + extern Long64_t atol64(const char* value); + extern const Int_t Ids_NullPtr; extern const Int_t Ids_RootDir; + extern const Int_t Ids_TSQLFile; extern const Int_t Ids_StreamerInfos; extern const Int_t Ids_FirstKey; extern const Int_t Ids_FirstObject; @@ -234,9 +245,14 @@ namespace sqlio { extern const char* KeysTable; extern const char* KeysTableIndex; extern const char* KT_Name; + extern const char* KT_Title; extern const char* KT_Datetime; extern const char* KT_Cycle; extern const char* KT_Class; + + extern const char* DT_Create; + extern const char* DT_Modified; + extern const char* DT_UUID; extern const char* ObjectsTable; extern const char* ObjectsTableIndex; diff --git a/sql/src/TBufferSQL2.cxx b/sql/src/TBufferSQL2.cxx index 6ff6667e260..908a5e9714b 100644 --- a/sql/src/TBufferSQL2.cxx +++ b/sql/src/TBufferSQL2.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TBufferSQL2.cxx,v 1.7 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TBufferSQL2.cxx,v 1.8 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -24,8 +24,10 @@ #include "TObjArray.h" #include "TROOT.h" +#include "TDataType.h" #include "TClass.h" #include "TClassTable.h" +#include "TMap.h" #include "TExMap.h" #include "TMethodCall.h" #include "TStreamerInfo.h" @@ -44,14 +46,30 @@ #include "TSQLFile.h" #include "TSQLClassInfo.h" +#ifdef R__VISUAL_CPLUSPLUS +#define FLong64 "%I64d" +#define FULong64 "%I64u" +#else +#ifdef R__B64 +#define FLong64 "%ld" +#define FULong64 "%lu" +#else +#define FLong64 "%lld" +#define FULong64 "%llu" +#endif +#endif + ClassImp(TBufferSQL2); //______________________________________________________________________________ TBufferSQL2::TBufferSQL2() : TBuffer(), - fSQL(0) + fSQL(0), + fStructure(0), + fObjMap(0), + fPoolsMap(0) { - // Default constructor + // Default constructor, should not be used } //______________________________________________________________________________ @@ -61,19 +79,21 @@ TBufferSQL2::TBufferSQL2(TBuffer::EMode mode) : fStructure(0), fStk(0), fObjMap(0), - fIdArray(0), fErrorFlag(0), fExpectedChain(kFALSE), fCompressLevel(0), fReadVersionBuffer(-1), fObjIdCounter(1), - fIgnoreVerification(kFALSE) + fIgnoreVerification(kFALSE), + fObjectsInfos(0), + fPoolsMap(0) { // Creates buffer object to serailize/deserialize data to/from sql. // Mode should be either TBuffer::kRead or TBuffer::kWrite. SetParent(0); SetBit(kCannotHandleMemberWiseStreaming); + SetBit(kTextBasedStreaming); } //______________________________________________________________________________ @@ -83,12 +103,13 @@ TBufferSQL2::TBufferSQL2(TBuffer::EMode mode, TSQLFile* file) : fStructure(0), fStk(0), fObjMap(0), - fIdArray(0), fErrorFlag(0), fExpectedChain(kFALSE), fCompressLevel(0), fReadVersionBuffer(-1), - fObjIdCounter(1) + fObjIdCounter(1), + fObjectsInfos(0), + fPoolsMap(0) { // Creates buffer object to serailize/deserialize data to/from sql. // This constructor should be used, if data from buffer supposed to be stored in file. @@ -98,6 +119,7 @@ TBufferSQL2::TBufferSQL2(TBuffer::EMode mode, TSQLFile* file) : // for TClonesArray recognize if this is special case SetBit(kCannotHandleMemberWiseStreaming); + SetBit(kTextBasedStreaming); SetParent(file); fSQL = file; @@ -110,27 +132,25 @@ TBufferSQL2::~TBufferSQL2() { // destroy sql buffer if (fObjMap) delete fObjMap; - if (fIdArray) delete fIdArray; if (fStructure!=0) { delete fStructure; fStructure = 0; } + + if (fObjectsInfos!=0) { + fObjectsInfos->Delete(); + delete fObjectsInfos; + } + + if (fPoolsMap!=0) { + fPoolsMap->DeleteValues(); + delete fPoolsMap; + } } //______________________________________________________________________________ -TSQLStructure* TBufferSQL2::SqlWrite(const TObject* obj, Int_t objid) -{ - // Convert object, derived from TObject class to sql structures - // Return pointer on created TSQLStructure - // TSQLStructure object will be owned by TBufferSQL2 - - if (obj==0) return SqlWrite(0,0, objid); - else return SqlWrite(obj, obj->IsA(), objid); -} - -//______________________________________________________________________________ -TSQLStructure* TBufferSQL2::SqlWrite(const void* obj, const TClass* cl, Int_t objid) +TSQLStructure* TBufferSQL2::SqlWriteAny(const void* obj, const TClass* cl, Long64_t objid) { // Convert object of any class to sql structures // Return pointer on created TSQLStructure @@ -140,6 +160,7 @@ TSQLStructure* TBufferSQL2::SqlWrite(const void* obj, const TClass* cl, Int_t ob fStructure = 0; + fFirstObjId = objid; fObjIdCounter = objid; SqlWriteObject(obj, cl); @@ -155,7 +176,7 @@ TSQLStructure* TBufferSQL2::SqlWrite(const void* obj, const TClass* cl, Int_t ob } //______________________________________________________________________________ -void* TBufferSQL2::SqlReadAny(Int_t objid, void* obj, TClass** cl) +void* TBufferSQL2::SqlReadAny(Long64_t keyid, Long64_t objid, TClass** cl, void* obj) { // Recreate object from sql structure. // Return pointer to read object. @@ -164,59 +185,113 @@ void* TBufferSQL2::SqlReadAny(Int_t objid, void* obj, TClass** cl) if (cl) *cl = 0; if (fSQL==0) return 0; - fCurrentData=0; + fCurrentData = 0; fErrorFlag = 0; fReadVersionBuffer = -1; + + fObjectsInfos = fSQL->SQLObjectsInfo(keyid); +// fObjectsInfos = 0; + fFirstObjId = objid; + fLastObjId = objid; + if (fObjectsInfos!=0) { + TSQLObjectInfo* objinfo = (TSQLObjectInfo*) fObjectsInfos->Last(); + if (objinfo!=0) fLastObjId = objinfo->GetObjId(); + } return SqlReadObjectDirect(obj, cl, objid); } //______________________________________________________________________________ -void TBufferSQL2::WriteObject(const TObject *obj) +Bool_t TBufferSQL2::SqlObjectInfo(Long64_t objid, TString& clname, Version_t& version) { - // Convert object into sql structures. - // !!! Should be used only by TBufferSQL2 itself. - // Use SqlWrite() functions to convert your object to sql - // Redefined here to avoid gcc 3.x warning +// Returns object info like classname and version +// Should be taken from buffer, which is produced in the begginnig - TBuffer::WriteObject(obj); + if ((objid<0) || (fObjectsInfos==0)) return kFALSE; + + // if (fObjectsInfos==0) return fSQL->SQLObjectInfo(objid, clname, version); + + // suppose that objects info are sorted out + + Long64_t shift = objid - fFirstObjId; + + TSQLObjectInfo* info = 0; + if ((shift>=0) && (shift<=fObjectsInfos->GetLast())) { + info = (TSQLObjectInfo*) fObjectsInfos->At(shift); + if (info->GetObjId()!=objid) info = 0; + } + + if (info==0) { + // I hope, i will never get inside it + Info("SqlObjectInfo", "Standard not works %lld", objid); + for (Int_t n=0;n<=fObjectsInfos->GetLast();n++) { + info = (TSQLObjectInfo*) fObjectsInfos->At(n); + if (info->GetObjId()==objid) break; + info = 0; + } + } + + if (info==0) return kFALSE; + + clname = info->GetObjClassName(); + version = info->GetObjVersion(); + return kTRUE; } + //______________________________________________________________________________ -Bool_t TBufferSQL2::ProcessPointer(const void* ptr, Int_t& objid) +TSQLObjectData* TBufferSQL2::SqlObjectData(Long64_t objid, TSQLClassInfo* sqlinfo) { - // Return SqlObjectId_Null, if ptr is null or - // id of object which was already stored in buffer + if (!sqlinfo->IsClassTableExist()) + return fSQL->GetObjectClassData(objid, sqlinfo); + + TSQLObjectDataPool* pool = 0; + + if (fPoolsMap!=0) + pool = (TSQLObjectDataPool*) fPoolsMap->GetValue(sqlinfo); + + if ((pool==0) && (fLastObjId>=fFirstObjId)) { + if (gDebug>4) Info("SqlObjectData","Before request to %s",sqlinfo->GetClassTableName()); + TSQLResult *alldata = fSQL->GetNormalClassDataAll(fFirstObjId, fLastObjId, sqlinfo); + if (gDebug>4) Info("SqlObjectData","After request res = %x",alldata); + if (alldata==0) { + Error("SqlObjectData","Cannot get data from table %s",sqlinfo->GetClassTableName()); + return 0; + } - if (ptr==0) { - objid = 0; - } else { - if (fObjMap==0) return kFALSE; - ULong_t hash = TMath::Hash(&ptr, sizeof(void*)); - Long_t storedobjid = fObjMap->GetValue(hash, (Long_t) ptr); - if (storedobjid==0) return kFALSE; + if (fPoolsMap==0) fPoolsMap = new TMap(); + pool = new TSQLObjectDataPool(sqlinfo, alldata); + fPoolsMap->Add(sqlinfo, pool); + } - objid = storedobjid; + if (pool==0) return 0; + + if (pool->GetSqlInfo()!=sqlinfo) { + Error("SqlObjectData","Missmatch in pools map !!! CANNOT BE !!!"); + return 0; } - return kTRUE; + TSQLResult *classdata = pool->GetClassData(); + + TSQLRow* row = pool->GetObjectRow(objid); + if (row==0) { + Error("SqlObjectData","Can not find row for objid = %lld in table %s", objid, sqlinfo->GetClassTableName()); + return 0; + } + TSQLResult *blobdata = fSQL->GetBlobClassData(objid, sqlinfo); + return new TSQLObjectData(sqlinfo, objid, classdata, row, blobdata); } //______________________________________________________________________________ -void TBufferSQL2::RegisterPointer(const void* ptr, Int_t objid) +void TBufferSQL2::WriteObject(const TObject *obj) { - // Register pair of object id, in object map - // Object id is used to indentify object in tables - - if ((ptr==0) || (objid==sqlio::Ids_NullPtr)) return; - - ULong_t hash = TMath::Hash(&ptr, sizeof(void*)); - - if (fObjMap==0) fObjMap = new TExMap(); + // Convert object into sql structures. + // !!! Should be used only by TBufferSQL2 itself. + // Use SqlWrite() functions to convert your object to sql + // Redefined here to avoid gcc 3.x warning - if (fObjMap->GetValue(hash, (Long_t) ptr)==0) - fObjMap->Add(hash, (Long_t) ptr, (Long_t) objid); + TBuffer::WriteObject(obj); } //______________________________________________________________________________ @@ -231,11 +306,21 @@ Int_t TBufferSQL2::SqlWriteObject(const void* obj, const TClass* cl, TMemberStre PushStack(); - Int_t objid = 0; + Long64_t objid = -1; if (cl==0) obj = 0; - - if (ProcessPointer(obj, objid)) { + + if (obj==0) + objid = 0; + else + if (fObjMap!=0) { + ULong_t hash = TMath::Hash(&obj, sizeof(void*)); + Long_t value = fObjMap->GetValue(hash, (Long_t) obj); + if (value>0) + objid = fFirstObjId + value - 1; + } + + if (objid>=0) { Stack()->SetObjectPointer(objid); PopStack(); return objid; @@ -244,7 +329,11 @@ Int_t TBufferSQL2::SqlWriteObject(const void* obj, const TClass* cl, TMemberStre objid = fObjIdCounter++; Stack()->SetObjectRef(objid, cl); - RegisterPointer(obj, objid); + + ULong_t hash = TMath::Hash(&obj, sizeof(void*)); + if (fObjMap==0) fObjMap = new TExMap(); + if (fObjMap->GetValue(hash, (Long_t) obj)==0) + fObjMap->Add(hash, (Long_t) obj, (Long_t) objid - fFirstObjId + 1); if (streamer!=0) (*streamer)(*this, (void*) obj, streamer_index); @@ -279,21 +368,30 @@ void* TBufferSQL2::SqlReadObject(void* obj, TClass** cl, TMemberStreamer *stream fErrorFlag = 1; return obj; } + + Long64_t objid = -1; + sscanf(refid, FLong64, &objid); if (!fCurrentData->IsBlobData() || fCurrentData->VerifyDataType(sqlio::ObjectPtr,kFALSE)) - if (strcmp(refid,"0")==0) { + if (objid==0) { obj = 0; findptr = kTRUE; } else - if ((fIdArray!=0) && (fObjMap!=0)) { - TNamed* identry = (TNamed*) fIdArray->FindObject(refid); - if (identry!=0) { - obj = (void*) fObjMap->GetValue((Long_t) fIdArray->IndexOf(identry)); - if (cl) *cl = gROOT->GetClass(identry->GetTitle()); - findptr = kTRUE; - } + if (objid==-1) { + findptr = kTRUE; + } else + if ((fObjMap!=0) && (objid>=fFirstObjId)) { + void* obj1 = (void*) fObjMap->GetValue((Long_t) objid - fFirstObjId); + if (obj1!=0) { + obj = obj1; + findptr = kTRUE; + TString clname; + Version_t version; + if ((cl!=0) && SqlObjectInfo(objid, clname, version)) + *cl = gROOT->GetClass(clname); } + } if ((gDebug>3) && findptr) cout << " Found pointer " << (obj ? obj : 0) @@ -311,18 +409,16 @@ void* TBufferSQL2::SqlReadObject(void* obj, TClass** cl, TMemberStreamer *stream return obj; } - Int_t objid = atoi(refid); - fCurrentData->ShiftToNextValue(); - if (gDebug>2) + if ((gDebug>2) || (objid<0)) cout << "Found object reference " << objid << endl; return SqlReadObjectDirect(obj, cl, objid, streamer, streamer_index); } //______________________________________________________________________________ -void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMemberStreamer *streamer, Int_t streamer_index) +void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Long64_t objid, TMemberStreamer *streamer, Int_t streamer_index) { // Read object data. // Class name and version are taken from special objects table. @@ -330,7 +426,10 @@ void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMem TString clname; Version_t version; - if (!fSQL->GetObjectData(objid, clname, version)) return obj; + if (!SqlObjectInfo(objid, clname, version)) return obj; + + if (gDebug>2) + Info("SqlReadObjectDirect","objid = %lld clname = %s ver = %d",objid, clname.Data(), version); TSQLClassInfo* sqlinfo = fSQL->RequestSQLClassInfo(clname.Data(), version); @@ -342,19 +441,9 @@ void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMem if (obj==0) obj = objClass->New(); - TString strid; - strid.Form("%d", objid); - - if (fIdArray==0) { - fIdArray = new TObjArray; - fIdArray->SetOwner(kTRUE); - } - TNamed* nid = new TNamed(strid.Data(), objClass->GetName()); - fIdArray->Add(nid); - if (fObjMap==0) fObjMap = new TExMap(); - fObjMap->Add((Long_t) fIdArray->IndexOf(nid), (Long_t) obj); + fObjMap->Add((Long_t) objid - fFirstObjId, (Long_t) obj); PushStack()->SetObjectRef(objid, objClass); @@ -366,10 +455,10 @@ void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMem TSQLObjectData* objdata = new TSQLObjectData; if (objClass==TObject::Class()) - TSQLStructure::UnpackTObject(fSQL, objdata, objid, version); + TSQLStructure::UnpackTObject(fSQL, this, objdata, objid, version); else if (objClass==TString::Class()) - TSQLStructure::UnpackTString(fSQL, objdata, objid, version); + TSQLStructure::UnpackTString(fSQL, this, objdata, objid, version); Stack()->AddObjectData(objdata); fCurrentData = objdata; @@ -378,7 +467,7 @@ void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Int_t objid, TMem // then streamer functions of TStreamerInfo class fReadVersionBuffer = version; } else { - TSQLObjectData* objdata = fSQL->GetObjectClassData(objid, sqlinfo); + TSQLObjectData* objdata = SqlObjectData(objid, sqlinfo); if ((objdata==0) || !objdata->PrepareForRawData()) { Error("SqlReadObjectDirect","No found raw data for obj %d in class %s version %d table", objid, clname.Data(), version); fErrorFlag = 1; @@ -419,54 +508,10 @@ void TBufferSQL2::IncrementLevel(TStreamerInfo* info) PushStack()->SetStreamerInfo(info); - fExpectedChain = kFALSE; - if (gDebug>2) - cout << " IncrementLevel " << info->GetClass()->GetName() << endl; - - if (IsReading()) { - Int_t objid = 0; - - Bool_t isclonesarray = Stack()->IsClonesArray(); - - if (isclonesarray) { - // nothing to do, data will be read from raw data as before - return; - } - - if ((fCurrentData!=0) && fCurrentData->IsBlobData() && - fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE)) { - objid = atoi(fCurrentData->GetValue()); - fCurrentData->ShiftToNextValue(); - TString sobjid; - sobjid.Form("%d",objid); - Stack()->ChangeValueOnly(sobjid.Data()); - } else - objid = Stack()->DefineObjectId(); - if (objid<0) { - Error("IncrementLevel","cannot define object id"); - fErrorFlag = 1; - return; - } - - TSQLClassInfo* sqlinfo = fSQL->RequestSQLClassInfo(info->GetName(), info->GetClassVersion()); - if (info==0) { - Error("IncrementLevel","Can not find table for class %s version %d",info->GetName(), info->GetClassVersion()); - fErrorFlag = 1; - return; - } - - TSQLObjectData* objdata = fSQL->GetObjectClassData(objid, sqlinfo); - if (objdata==0) { - Error("IncrementLevel","Request error for data of object %d for class %s version %d", objid, info->GetName(), info->GetClassVersion()); - fErrorFlag = 1; - return; - } - - Stack()->AddObjectData(objdata); - - fCurrentData = objdata; - } + cout << " IncrementLevel " << info->GetName() << endl; + + WorkWithClass(info->GetName(), info->GetClassVersion()); } //______________________________________________________________________________ @@ -512,14 +557,261 @@ void TBufferSQL2::SetStreamerElementNumber(Int_t number) fExpectedChain = ((elem_type>0) && (elem_type<20)) && (comp_type - elem_type == TStreamerInfo::kOffsetL); - WorkWithElement(elem, number); } +//______________________________________________________________________________ +void TBufferSQL2::ClassBegin(const TClass* cl, Version_t classversion) +{ + // This method inform buffer data of which class now + // will be streamed. When reading, classversion should be specified + // as was read by TBuffer::ReadVersion() call + // + // ClassBegin(), ClassEnd() & ClassMemeber() should be used in + // custom class streamers to specify which kind of data are + // now streamed to/from buffer. That information is used to correctly + // convert class data to/from "normal" sql tables with meaningfull names + // and correct datatypes. Without that functions data from custom streamer + // will be saved as "raw" data in special _streamer_ table one value after another + // Such MUST be used when object is written with standard ROOT streaming + // procedure, but should be read back in custom streamer. + // For example, custom streamer of TNamed class may look like: + +// void TNamed::Streamer(TBuffer &b) +// UInt_t R__s, R__c; +// if (b.IsReading()) { +// Version_t R__v = b.ReadVersion(&R__s, &R__c); +// b.ClassBegin(TNamed::Class(), R__v); +// b.ClassMember("TObject"); +// TObject::Streamer(b); +// b.ClassMember("fName","TString"); +// fName.Streamer(b); +// b.ClassMember("fTitle","TString"); +// fTitle.Streamer(b); +// b.ClassEnd(TNamed::Class()); +// b.SetBufferOffset(R__s+R__c+sizeof(UInt_t)); +// } else { +// TNamed::Class()->WriteBuffer(b,this); +// } + + if (classversion<0) classversion = cl->GetClassVersion(); + + PushStack()->SetCustomClass(cl, classversion); + + if (gDebug>2) Info("ClassBegin", cl->GetName()); + + WorkWithClass(cl->GetName(), classversion); +} + +//______________________________________________________________________________ +void TBufferSQL2::ClassEnd(const TClass* cl) +{ + // Method indicates end of streaming of classdata in custom streamer. + // See ClassBegin() method for more details. + + TSQLStructure* curr = Stack(); + if (curr->GetType()==TSQLStructure::kSqlCustomElement) PopStack(); // for element + PopStack(); // for streamerinfo + + // restore value of object data + fCurrentData = Stack()->GetObjectData(kTRUE); + + fExpectedChain = kFALSE; + + if (gDebug>2) Info("ClassEnd",cl->GetName()); +} + +//______________________________________________________________________________ +void TBufferSQL2::ClassMember(const char* name, const char* typeName, Int_t arrsize1, Int_t arrsize2) +{ + // Method indicates name and typename of class memeber, + // which should be now streamed in custom streamer + // Following combinations are supported: + // 1. name = "ClassName", typeName = 0 or typename==ClassName + // This is a case, when data of parent class "ClassName" should be streamed. + // For instance, if class directly inherited from TObject, custom + // streamer should include following code: + // b.ClassMember("TObject"); + // TObject::Streamer(b); + // 2. Basic data type + // b.ClassMember("fInt","Int_t"); + // b >> fInt; + // 3. Array of basic data types + // b.ClassMember("fArr","Int_t", 5); + // b.ReadFastArray(fArr, 5); + // 4. Object as data member + // b.ClassMemeber("fName","TString"); + // fName.Streamer(b); + // 5. Pointer on object as datamember + // b.ClassMemeber("fObj","TObject*"); + // b.StreamObject(b); + // arrsize1 and arrsize2 arguments (when specified) indicate first and + // second dimension of array. Can be used for array of basic types. + // For more details see ClassBegin() method description. + + if (typeName==0) typeName = name; + + if ((name==0) || (strlen(name)==0)) { + Error("ClassMember","Invalid member name"); + fErrorFlag = 1; + return; + } + + TString tname = typeName; + + Int_t typ_id = -1; + + if (strcmp(typeName,"raw:data")==0) + typ_id = TStreamerInfo::kMissing; + + if (typ_id<0) { + TDataType *dt = gROOT->GetType(typeName); + if (dt!=0) + if ((dt->GetType()>0) && (dt->GetType()<20)) + typ_id = dt->GetType(); + } + + if (typ_id<0) + if (strcmp(name, typeName)==0) { + TClass* cl = gROOT->GetClass(tname.Data()); + if (cl!=0) typ_id = TStreamerInfo::kBase; + } + + if (typ_id<0) { + Bool_t isptr = kFALSE; + if (tname[tname.Length()-1]=='*') { + tname.Resize(tname.Length()-1); + isptr = kTRUE; + } + TClass* cl = gROOT->GetClass(tname.Data()); + if (cl==0) { + Error("ClassMember","Invalid class specifier %s", typeName); + fErrorFlag = 1; + return; + } + + if (cl->IsTObject()) + typ_id = isptr ? TStreamerInfo::kObjectp : TStreamerInfo::kObject; + else + typ_id = isptr ? TStreamerInfo::kAnyp : TStreamerInfo::kAny; + + if ((cl==TString::Class()) && !isptr) + typ_id = TStreamerInfo::kTString; + } + + TStreamerElement* elem = 0; + + if (typ_id == TStreamerInfo::kMissing) { + elem = new TStreamerElement(name,"title",0, typ_id, "raw:data"); + } else + + if (typ_id==TStreamerInfo::kBase) { + TClass* cl = gROOT->GetClass(tname.Data()); + if (cl!=0) { + TStreamerBase* b = new TStreamerBase(tname.Data(), "title", 0); + b->SetBaseVersion(cl->GetClassVersion()); + elem = b; + } + } else + + if ((typ_id>0) && (typ_id<20)) { + elem = new TStreamerBasicType(name, "title", 0, typ_id, typeName); + } else + + if ((typ_id==TStreamerInfo::kObject) || + (typ_id==TStreamerInfo::kTObject) || + (typ_id==TStreamerInfo::kTNamed)) { + elem = new TStreamerObject(name, "title", 0, tname.Data()); + } else + + if (typ_id==TStreamerInfo::kObjectp) { + elem = new TStreamerObjectPointer(name, "title", 0, tname.Data()); + } else + + if (typ_id==TStreamerInfo::kAny) { + elem = new TStreamerObjectAny(name, "title", 0, tname.Data()); + } else + + if (typ_id==TStreamerInfo::kAnyp) { + elem = new TStreamerObjectAnyPointer(name, "title", 0, tname.Data()); + } else + + if (typ_id==TStreamerInfo::kTString) { + elem = new TStreamerString(name, "title", 0); + } + + if (elem==0) { + Error("ClassMember","Invalid combination name = %s type = %s", name, typeName); + fErrorFlag = 1; + return; + } + + if (arrsize1>0) { + elem->SetArrayDim(arrsize2>0 ? 2 : 1); + elem->SetMaxIndex(0, arrsize1); + if (arrsize2>0) + elem->SetMaxIndex(1, arrsize2); + } + + // return stack to CustomClass node + if (Stack()->GetType()==TSQLStructure::kSqlCustomElement) PopStack(); + + fExpectedChain = kFALSE; + + // we indicate that there is no streamerinfo + WorkWithElement(elem, -1); +} + +//______________________________________________________________________________ +void TBufferSQL2::WorkWithClass(const char* classname, Version_t classversion) +{ + // This function is a part of IncrementLevel method. + // Also used in StartClass method + + fExpectedChain = kFALSE; + + if (IsReading()) { + Long64_t objid = 0; + + if ((fCurrentData!=0) && fCurrentData->IsBlobData() && + fCurrentData->VerifyDataType(sqlio::ObjectInst, kFALSE)) { + objid = atoi(fCurrentData->GetValue()); + fCurrentData->ShiftToNextValue(); + TString sobjid; + sobjid.Form("%lld",objid); + Stack()->ChangeValueOnly(sobjid.Data()); + } else + objid = Stack()->DefineObjectId(kTRUE); + if (objid<0) { + Error("WorkWithClass","cannot define object id"); + fErrorFlag = 1; + return; + } + + TSQLClassInfo* sqlinfo = fSQL->RequestSQLClassInfo(classname, classversion); + if (sqlinfo==0) { + Error("WorkWithClass","Can not find table for class %s version %d", classname, classversion); + fErrorFlag = 1; + return; + } + + TSQLObjectData* objdata = SqlObjectData(objid, sqlinfo); + if (objdata==0) { + Error("WorkWithClass","Request error for data of object %lld for class %s version %d", objid, classname, classversion); + fErrorFlag = 1; + return; + } + + Stack()->AddObjectData(objdata); + + fCurrentData = objdata; + } +} + //______________________________________________________________________________ void TBufferSQL2::WorkWithElement(TStreamerElement* elem, Int_t number) { - // This function is a part of SetStreamerElementNumber function. + // This function is a part of SetStreamerElementNumber method. // It is introduced for reading of data for specified data memeber of class. // Used also in ReadFastArray methods to resolve problem of compressed data, // when several data memebers of the same basic type streamed with single ...FastArray call @@ -527,7 +819,10 @@ void TBufferSQL2::WorkWithElement(TStreamerElement* elem, Int_t number) if (gDebug>2) cout << " TBufferSQL2::WorkWithElement " << elem->GetName() << endl; - PushStack()->SetStreamerElement(elem, number); + if (number>=0) + PushStack()->SetStreamerElement(elem, number); + else + PushStack()->SetCustomElement(elem); if (IsReading()) { @@ -539,7 +834,7 @@ void TBufferSQL2::WorkWithElement(TStreamerElement* elem, Int_t number) fCurrentData = Stack()->GetObjectData(kTRUE); - Int_t located = Stack()->LocateElementColumn(fSQL, fCurrentData); + Int_t located = Stack()->LocateElementColumn(fSQL, this, fCurrentData); if (located==TSQLStructure::kColUnknown) { Error("WorkWithElement","Cannot locate correct column in the table"); @@ -595,7 +890,7 @@ void TBufferSQL2::SetByteCount(UInt_t, Bool_t) Version_t TBufferSQL2::ReadVersion(UInt_t *start, UInt_t *bcnt, const TClass *) { // read version value from buffer - // actually version is normally defined by table name before + // actually version is normally defined by table name // and kept in intermediate variable fReadVersionBuffer Version_t res = 0; @@ -609,17 +904,17 @@ Version_t TBufferSQL2::ReadVersion(UInt_t *start, UInt_t *bcnt, const TClass *) if (gDebug>3) cout << "TBufferSQL2::ReadVersion from buffer = " << res << endl; } else - if ((fCurrentData!=0) && fCurrentData->IsBlobData() && - fCurrentData->VerifyDataType(sqlio::Version)) { - TString value = fCurrentData->GetValue(); - res = value.Atoi(); - if (gDebug>3) - cout << "TBufferSQL2::ReadVersion from blob " << fCurrentData->GetBlobName1() << " = " << res << endl; - fCurrentData->ShiftToNextValue(); - } else { - Error("ReadVersion", "No correspondent tags to read version"); - fErrorFlag = 1; - } + if ((fCurrentData!=0) && fCurrentData->IsBlobData() && + fCurrentData->VerifyDataType(sqlio::Version)) { + TString value = fCurrentData->GetValue(); + res = value.Atoi(); + if (gDebug>3) + cout << "TBufferSQL2::ReadVersion from blob " << fCurrentData->GetBlobName1() << " = " << res << endl; + fCurrentData->ShiftToNextValue(); + } else { + Error("ReadVersion", "No correspondent tags to read version"); + fErrorFlag = 1; + } return res; } @@ -1994,7 +2289,7 @@ Bool_t TBufferSQL2::SqlWriteBasic(ULong64_t value) // converts ULong64_t to string and creates correspondent sql structure char buf[50]; - sprintf(buf,"%llu", value); + sprintf(buf, FULong64, value); return SqlWriteValue(buf, sqlio::ULong64); } @@ -2066,7 +2361,7 @@ void TBufferSQL2::SqlReadBasic(Long64_t& value) const char* res = SqlReadValue(sqlio::Long64); if (res) - sscanf(res,"%lld", &value); + sscanf(res, FLong64, &value); else value = 0; } @@ -2164,7 +2459,7 @@ void TBufferSQL2::SqlReadBasic(ULong64_t& value) const char* res = SqlReadValue(sqlio::ULong64); if (res) - sscanf(res,"%llu", &value); + sscanf(res, FULong64, &value); else value = 0; } @@ -2205,9 +2500,9 @@ const char* TBufferSQL2::SqlReadCharStarValue() const char* res = SqlReadValue(sqlio::CharStar); if ((res==0) || (fSQL==0)) return 0; - Int_t objid = Stack()->DefineObjectId(); + Long64_t objid = Stack()->DefineObjectId(kTRUE); - Int_t strid = fSQL->IsLongStringCode(res, objid); + Int_t strid = fSQL->IsLongStringCode(objid, res); if (strid<=0) return res; fSQL->GetLongString(objid, strid, fReadBuffer); diff --git a/sql/src/TKeySQL.cxx b/sql/src/TKeySQL.cxx index ed98c666726..3a5ef2fecf1 100644 --- a/sql/src/TKeySQL.cxx +++ b/sql/src/TKeySQL.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TKeySQL.cxx,v 1.5 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TKeySQL.cxx,v 1.6 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -22,6 +22,7 @@ #include "TROOT.h" #include "TClass.h" #include "TBrowser.h" +#include "TDirectory.h" #include "Riostream.h" #include "TSQLResult.h" @@ -34,16 +35,15 @@ ClassImp(TKeySQL); //______________________________________________________________________________ TKeySQL::TKeySQL() : TKey(), - fFile(0), - fKeyId(-1) + fKeyId(-1), + fObjId(-1) { // default constructor } //______________________________________________________________________________ -TKeySQL::TKeySQL(TSQLFile* file, const TObject* obj, const char* name) : - TKey(), - fFile(file), +TKeySQL::TKeySQL(TDirectory* mother, const TObject* obj, const char* name, const char* title) : + TKey(mother), fKeyId(-1), fObjId(-1) { @@ -52,14 +52,15 @@ TKeySQL::TKeySQL(TSQLFile* file, const TObject* obj, const char* name) : if (name) SetName(name); else if (obj!=0) {SetName(obj->GetName()); fClassName=obj->ClassName();} else SetName("Noname"); + + if (title) SetTitle(title); - StoreObject((void*)obj, obj ? obj->IsA() : 0); + StoreKeyObject((void*)obj, obj ? obj->IsA() : 0); } //______________________________________________________________________________ -TKeySQL::TKeySQL(TSQLFile* file, const void* obj, const TClass* cl, const char* name) : - TKey(), - fFile(file), +TKeySQL::TKeySQL(TDirectory* mother, const void* obj, const TClass* cl, const char* name, const char* title) : + TKey(mother), fKeyId(-1), fObjId(-1) { @@ -68,21 +69,23 @@ TKeySQL::TKeySQL(TSQLFile* file, const void* obj, const TClass* cl, const char* if (name && *name) SetName(name); else SetName(cl ? cl->GetName() : "Noname"); - StoreObject(obj, cl); + if (title) SetTitle(title); + + StoreKeyObject(obj, cl); } //______________________________________________________________________________ -TKeySQL::TKeySQL(TSQLFile* file, Int_t keyid, Int_t dirid, Int_t objid, const char* name, +TKeySQL::TKeySQL(TDirectory* mother, Long64_t keyid, Long64_t objid, + const char* name, const char* title, const char* keydatetime, Int_t cycle, const char* classname) : - TKey(), - fFile(file), + TKey(mother), fKeyId(keyid), - fDirId(dirid), fObjId(objid) { // Create TKeySQL object, which correponds to single entry in keys table SetName(name); + if (title) SetTitle(title); TDatime dt(keydatetime); fDatime = dt; fCycle = cycle; @@ -96,25 +99,36 @@ TKeySQL::~TKeySQL() } //______________________________________________________________________________ -void TKeySQL::Browse(TBrowser *b) +Bool_t TKeySQL::IsKeyModified(const char* keyname, const char* keytitle, const char* keydatime, Int_t cycle, const char* classname) { -// Browse object corresponding to this key - - TObject *obj = gDirectory->GetList()->FindObject(GetName()); - if (obj && !obj->IsFolder()) { - if (obj->InheritsFrom(TCollection::Class())) - obj->Delete(); // delete also collection elements - delete obj; - obj = 0; - } - - if (!obj) - obj = ReadObj(); - - if (b && obj) { - obj->Browse(b); - b->SetRefreshFlag(kTRUE); - } +// Compares keydata with provided and return kTRUE if key was modified +// Used in TFile::StreamKeysForDirectory() method to verify data for that keys +// should be updated + + Int_t len1 = (GetName()==0) ? 0 : strlen(GetName()); + Int_t len2 = (keyname==0) ? 0 : strlen(keyname); + if (len1!=len2) return kTRUE; + if ((len1>0) && (strcmp(GetName(), keyname)!=0)) return kTRUE; + + len1 = (GetTitle()==0) ? 0 : strlen(GetTitle()); + len2 = (keytitle==0) ? 0 : strlen(keytitle); + if (len1!=len2) return kTRUE; + if ((len1>0) && (strcmp(GetTitle(), keytitle)!=0)) return kTRUE; + + const char* tm = GetDatime().AsSQLString(); + len1 = (tm==0) ? 0 : strlen(tm); + len2 = (keydatime==0) ? 0 : strlen(keydatime); + if (len1!=len2) return kTRUE; + if ((len1>0) && (strcmp(tm, keydatime)!=0)) return kTRUE; + + if (cycle!=GetCycle()) return kTRUE; + + len1 = (GetClassName()==0) ? 0 : strlen(GetClassName()); + len2 = (classname==0) ? 0 : strlen(classname); + if (len1!=len2) return kTRUE; + if ((len1>0) && (strcmp(GetClassName(), classname)!=0)) return kTRUE; + + return kFALSE; } //______________________________________________________________________________ @@ -123,88 +137,47 @@ void TKeySQL::Delete(Option_t * /*option*/) // Removes key from current directory // Note: TKeySQL object is not deleted. You still have to call "delete key" - if (fFile!=0) - fFile->DeleteKeyFromDB(GetDBKeyId()); + TSQLFile* f = (TSQLFile*) GetFile(); + + if (f!=0) + f->DeleteKeyFromDB(GetDBKeyId()); - gDirectory->GetListOfKeys()->Remove(this); + fMotherDir->GetListOfKeys()->Remove(this); } //______________________________________________________________________________ -void TKeySQL::StoreObject(const void* obj, const TClass* cl) +Long64_t TKeySQL::GetDBDirId() const { -// convert object to sql statements and store them in DB - - TObjArray cmds; - Bool_t needcommit = kFALSE; - - fCycle = fFile->AppendKey(this); - - fKeyId = fFile->DefineNextKeyId(); - - fObjId = fFile->VerifyObjectTable(); - if (fObjId<=0) fObjId = 1; - else fObjId++; + // return sql id of parent directory + return GetMotherDir() ? GetMotherDir()->GetSeekDir() : 0; +} - TBufferSQL2 buffer(TBuffer::kWrite, fFile); +//______________________________________________________________________________ +void TKeySQL::StoreKeyObject(const void* obj, const TClass* cl) +{ + TSQLFile* f = (TSQLFile*) GetFile(); + + fCycle = GetMotherDir()->AppendKey(this); - TSQLStructure* s = buffer.SqlWrite(obj, cl, fObjId); + fKeyId = f->DefineNextKeyId(); - if ((buffer.GetErrorFlag()>0) || (s==0)) { - Error("StoreObject","Cannot convert object data to TSQLStructure"); - goto zombie; - } + fObjId = f->StoreObjectInTables(fKeyId, obj, cl); if (cl) fClassName = cl->GetName(); - if (fFile->GetUseTransactions()==TSQLFile::kTransactionsAuto) { - fFile->SQLStartTransaction(); - needcommit = kTRUE; - } - - // here tables may be already created, therefore - // it should be protected by transactions operations - if (!s->ConvertToTables(fFile, fKeyId, &cmds)) { - Error("StoreObject","Cannot convert to SQL statements"); - goto zombie; - } - - if (!fFile->SQLApplyCommands(&cmds)) { - Error("StoreObject","Cannot correctly store object data in database"); - goto zombie; - } - - // commit here, while objects data is already stored - if (needcommit) { - fFile->SQLCommit(); - needcommit = kFALSE; - } - - cmds.Delete(); - - fDatime.Set(); - - if (!fFile->WriteKeyData(GetDBKeyId(), - sqlio::Ids_RootDir, // later parent directory id should be - GetDBObjId(), - GetName(), - GetDatime().AsSQLString(), - GetCycle(), - GetClassName())) { - // cannot add entry to keys table - Error("StoreObject","Cannot write data to key tables"); - // delete everything relevant for that key - fFile->DeleteKeyFromDB(GetDBKeyId()); - goto zombie; + if (GetDBObjId()>=0) { + fDatime.Set(); + if (!f->WriteKeyData(this)) { + // cannot add entry to keys table + Error("StoreObject","Cannot write data to key tables"); + // delete everything relevant for that key + f->DeleteKeyFromDB(GetDBKeyId()); + fObjId = -1; + } } - - return; -zombie: - if (needcommit) - fFile->SQLRollback(); - - cmds.Delete(); - gDirectory->GetListOfKeys()->Remove(this); + if (GetDBObjId()<0) + GetMotherDir()->GetListOfKeys()->Remove(this); // fix me !!! One should delete object by other means // delete this; } @@ -219,7 +192,7 @@ Int_t TKeySQL::Read(TObject* tobj) if (tobj==0) return 0; - void* res = SqlReadAny(tobj, 0); + void* res = ReadKeyObject(tobj, 0); return res==0 ? 0 : 1; } @@ -230,9 +203,20 @@ TObject* TKeySQL::ReadObj() // Read object derived from TObject class // If it is not TObject or in case of error, return 0 - TObject* tobj = (TObject*) SqlReadAny(0, TObject::Class()); + TObject* tobj = (TObject*) ReadKeyObject(0, TObject::Class()); - if ((tobj!=0) && gROOT->GetForceStyle()) tobj->UseCurrentStyle(); + if (tobj!=0) { + if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); + if (tobj->IsA() == TDirectory::Class()) { + TDirectory *dir = (TDirectory*) tobj; + dir->SetName(GetName()); + dir->SetTitle(GetTitle()); + //dir->SetSeekDir(GetDBKeyId()); + dir->ReadKeys(); + dir->SetMother(fMotherDir); + fMotherDir->Append(dir); + } + } return tobj; } @@ -242,19 +226,22 @@ void* TKeySQL::ReadObjectAny(const TClass* expectedClass) { // read object of any type from SQL database - return SqlReadAny(0, expectedClass); + return ReadKeyObject(0, expectedClass); } //______________________________________________________________________________ -void* TKeySQL::SqlReadAny(void* obj, const TClass* expectedClass) +void* TKeySQL::ReadKeyObject(void* obj, const TClass* expectedClass) { - if ((fKeyId<=0) || (fFile==0)) return 0; - TBufferSQL2 buffer(TBuffer::kRead, fFile); + TSQLFile* f = (TSQLFile*) GetFile(); + + if ((GetDBKeyId()<=0) || (f==0)) return obj; + + TBufferSQL2 buffer(TBuffer::kRead, f); TClass* cl = 0; - void* res = buffer.SqlReadAny(fObjId, obj, &cl); + void* res = buffer.SqlReadAny(GetDBKeyId(), GetDBObjId(), &cl, obj); if ((cl==0) || (res==0)) return 0; diff --git a/sql/src/TSQLFile.cxx b/sql/src/TSQLFile.cxx index 22ae48dd780..775fada623b 100644 --- a/sql/src/TSQLFile.cxx +++ b/sql/src/TSQLFile.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLFile.cxx,v 1.5 2005/12/07 14:59:57 rdm Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLFile.cxx,v 1.6 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -388,6 +388,7 @@ TSQLFile::TSQLFile() : fUseTransactions(0), fUseIndexes(0), fModifyCounter(0), + fQuerisCounter(0), fBasicTypes(0), fOtherTypes(0), fUserName(), @@ -409,6 +410,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const fUseTransactions(0), fUseIndexes(0), fModifyCounter(0), + fQuerisCounter(0), fBasicTypes(mysql_BasicTypes), fOtherTypes(mysql_OtherTypes), fUserName(user), @@ -472,6 +474,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const fCache = 0; fProcessIDs = 0; fNProcessIDs= 0; + fSeekDir = sqlio::Ids_RootDir; fOption = option; fOption.ToUpper(); @@ -883,17 +886,25 @@ Int_t TSQLFile::ReOpen(Option_t* mode) } //______________________________________________________________________________ -TKey* TSQLFile::CreateKey(const TObject* obj, const char* name, Int_t ) +TKey* TSQLFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t ) { // create SQL key, which will store object in data base - return new TKeySQL(this, obj, name); + return new TKeySQL(mother, obj, name); } //______________________________________________________________________________ -TKey* TSQLFile::CreateKey(const void* obj, const TClass* cl, const char* name, Int_t ) +TKey* TSQLFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t ) { // create SQL key, which will store object in data base - return new TKeySQL(this, obj, cl, name); + return new TKeySQL(mother, obj, cl, name); +} + +//______________________________________________________________________________ +void TSQLFile::WriteHeader() +{ + // Write file info like configurations, title, UUID and other + +// WriteSpecialObject(sqlio::Ids_TSQLFile, this, GetName(), GetTitle()); } //______________________________________________________________________________ @@ -908,8 +919,6 @@ void TSQLFile::WriteStreamerInfo() // do not write anything when no basic tables was created if (!IsTablesExists()) return; - Int_t keyid = sqlio::Ids_StreamerInfos; - if (gDebug>1) Info("WriteStreamerInfo","Saving streamer infos to database"); @@ -929,27 +938,60 @@ void TSQLFile::WriteStreamerInfo() if (list.GetSize()==0) return; fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile - DeleteKeyFromDB(keyid); + WriteSpecialObject(sqlio::Ids_StreamerInfos, &list, "StreamerInfo", "StreamerInfos of this file"); - Int_t objid = VerifyObjectTable(); - if (objid<=0) objid = 1; - else objid++; + fClassIndex->fArray[0] = 0; //to prevent adding classes in TStreamerInfo::TagFile +} - TBufferSQL2 buffer(TBuffer::kWrite, this); +//______________________________________________________________________________ +Bool_t TSQLFile::WriteSpecialObject(Long64_t keyid, TObject* obj, const char* name, const char* title) +{ +// write special kind of object like streamer infos or file itself +// keys for that objects should exist in tables but not indicated in list of keys, +// therefore users can not get them with TDirectory::Get() method + + DeleteKeyFromDB(keyid); + if (obj==0) return kTRUE; - TSQLStructure* s = buffer.SqlWrite(&list, list.IsA(), objid); - if (gDebug>4) - s->Print("*"); + Long64_t objid = StoreObjectInTables(keyid, obj, obj->IsA()); - TObjArray cmds; - TDatime now; - if (s->ConvertToTables(this, keyid, &cmds)) - if (SQLApplyCommands(&cmds)) - WriteKeyData(keyid, sqlio::Ids_RootDir, objid, "StreamerInfo", now.AsSQLString(), 1, list.IsA()->GetName()); + if (objid>0) { + TDatime now; + + TKeySQL* key = new TKeySQL(this, keyid, objid, + name, title, + now.AsSQLString(), 1, obj->ClassName()); + WriteKeyData(key); + delete key; + } + + return (objid>0); +} - cmds.Delete(); +//______________________________________________________________________________ +TObject* TSQLFile::ReadSpecialObject(Long64_t keyid, TObject* obj) +{ +// Read data of special kind of objects - fClassIndex->fArray[0] = 0; //to prevent adding classes in TStreamerInfo::TagFile + TKeySQL* key = 0; + + StreamKeysForDirectory(this, kFALSE, keyid, &key); + if (key==0) return obj; + + TBufferSQL2 buffer(TBuffer::kRead, this); + + TClass* cl = 0; + + void* res = buffer.SqlReadAny(key->GetDBKeyId(), key->GetDBObjId(), &cl, obj); + + if ((cl==TSQLFile::Class()) && (res!=0) && (obj==this)) { + // name should not be preserved while name of database may be was changed + SetTitle(key->GetTitle()); + } + + delete key; + + return (TObject*) res; } //______________________________________________________________________________ @@ -963,53 +1005,106 @@ TList* TSQLFile::GetStreamerInfoList() // Hopefully, problem will be solved soon return new TList; + + if (gDebug>1) + Info("GetStreamerInfoList","Start reading of streamer infos"); + + TObject* obj = ReadSpecialObject(sqlio::Ids_StreamerInfos); + + TList* list = dynamic_cast<TList*> (obj); + if (list==0) { delete obj; list = new TList; } + + return list; } //______________________________________________________________________________ void TSQLFile::SaveToDatabase() { // save data which is not yet in Database - // Typically this is streamerinfos structures + // Typically this is streamerinfos structures or if (fSQL==0) return; + WriteStreamerInfo(); + WriteHeader(); } //______________________________________________________________________________ -Bool_t TSQLFile::ReadKeysForDirectory(TDirectory* dir, Int_t dir_id) +Int_t TSQLFile::StreamKeysForDirectory(TDirectory* dir, Bool_t doupdate, Long64_t specialkeyid, TKeySQL** specialkey) { - // read keys for specified direccctory - - if ((dir==0) || (dir_id<0)) return kFALSE; + // read keys for specified directory (when update == kFALSE) + // or update value for modified keys when update == kTRUE + // Returns number of succesfully read keys or -1 if error + if (dir==0) return -1; + const char* quote = SQLIdentifierQuote(); + + Long64_t dirid = dir->GetSeekDir(); TString sqlcmd; - sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%d", + sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::KeysTable, quote, - quote, SQLDirIdColumn(), quote, dir_id); + quote, SQLDirIdColumn(), quote, dirid); + if (specialkeyid>=0) { + TString buf; + buf.Form(" AND %s%s%s=%lld", quote, SQLKeyIdColumn(), quote, specialkeyid); + sqlcmd += buf; + } + TSQLResult* res = SQLQuery(sqlcmd.Data(), 2); - if (res==0) return kFALSE; + if (res==0) return -1; + + Int_t nkeys = res->GetRowCount(); - for(Int_t nrow=0;nrow<res->GetRowCount();nrow++) { + for(Int_t nrow=0;nrow<nkeys;nrow++) { TSQLRow* row = res->Next(); - - Int_t keyid = atoi((*row)[0]); + + Long64_t keyid = sqlio::atol64((*row)[0]); // Int_t dirid = atoi((*row)[1]); - Int_t objid = atoi((*row)[2]); - - Int_t cycle = atoi((*row)[5]); - - if (keyid!=sqlio::Ids_StreamerInfos) { - TKeySQL* key = new TKeySQL(this, keyid, dir_id, objid, (*row)[3], (*row)[4], cycle, (*row)[6]); - dir->AppendKey(key); - } + Long64_t objid = sqlio::atol64((*row)[2]); + const char* keyname = (*row)[3]; + const char* keytitle = (*row)[4]; + const char* keydatime = (*row)[5]; + Int_t cycle = atoi((*row)[6]); + const char* classname = (*row)[7]; + + if (gDebug>4) + cout << " Reading keyid = " << keyid << " name = " << keyname << endl; + + if ((keyid>=sqlio::Ids_FirstKey) || (keyid==specialkeyid)) + if (doupdate) { + TKeySQL* key = FindSQLKey(dir, keyid); + + if (key==0) { + Error("StreamKeysForDirectory","Key with id %d not exist in list", keyid); + nkeys = -1; // this will finish execution + } else + if (key->IsKeyModified(keyname, keytitle, keydatime, cycle, classname)) + UpdateKeyData(key); + + } else { + TKeySQL* key = new TKeySQL(dir, keyid, objid, + keyname, keytitle, + keydatime, cycle, classname); + if (specialkey!=0) + { *specialkey = key; nkeys = 1; } + else + dir->GetListOfKeys()->Add(key); + } delete row; } + + delete res; - return kTRUE; + if (gDebug>4) { + Info("StreamKeysForDirectory","dir = %s numread = %d",dir->GetName(), nkeys); + dir->GetListOfKeys()->Print("*"); + } + + return nkeys; } //______________________________________________________________________________ @@ -1026,11 +1121,16 @@ void TSQLFile::InitSqlDatabase(Bool_t create) if (!create) { Bool_t ok = ReadConfigurations(); + // read data corresponding to TSQLFile if (ok) { ReadStreamerInfo(); - ok = ReadKeysForDirectory(this, sqlio::Ids_RootDir); +// ok = (ReadSpecialObject(sqlio::Ids_TSQLFile, this) != 0); } + // read list of keys + if (ok) + ok = StreamKeysForDirectory(this, kFALSE)>=0; + if (!ok) { Error("InitSqlDatabase", "Cannot detect proper tabled in database. Close."); Close(); @@ -1132,11 +1232,11 @@ void TSQLFile::CreateBasicTables() SQLQuery(sqlcmd.Data()); } - sqlcmd.Form("CREATE TABLE %s%s%s (%s %s, %s %s)", + sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s)", quote, sqlio::ConfigTable, quote, - sqlio::CT_Field, SQLSmallTextType(), - sqlio::CT_Value, SQLSmallTextType()); - if (fTablesType.Length()>0) { + quote, sqlio::CT_Field, quote, SQLSmallTextType(), + quote, sqlio::CT_Value, quote, SQLSmallTextType()); + if ((fTablesType.Length()>0) && IsMySQL()) { sqlcmd +=" TYPE="; sqlcmd += fTablesType; } @@ -1169,17 +1269,18 @@ void TSQLFile::CreateBasicTables() SQLQuery(sqlcmd.Data()); } - sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s %s, %s %s, %s %s, %s %s)", + sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)", quote, sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote, SQLIntType(), quote, SQLDirIdColumn(), quote, SQLIntType(), quote, SQLObjectIdColumn(), quote, SQLIntType(), - sqlio::KT_Name, SQLSmallTextType(), - sqlio::KT_Datetime, SQLDatetimeType(), - sqlio::KT_Cycle, SQLIntType(), - sqlio::KT_Class, SQLSmallTextType()); + quote, sqlio::KT_Name, quote, SQLSmallTextType(), + quote, sqlio::KT_Title, quote, SQLSmallTextType(), + quote, sqlio::KT_Datetime, quote, SQLDatetimeType(), + quote, sqlio::KT_Cycle, quote, SQLIntType(), + quote, sqlio::KT_Class, quote, SQLSmallTextType()); - if (fTablesType.Length()>0) { + if ((fTablesType.Length()>0) && IsMySQL()) { sqlcmd +=" TYPE="; sqlcmd += fTablesType; } @@ -1413,6 +1514,8 @@ TSQLResult* TSQLFile::SQLQuery(const char* cmd, Int_t flag, Bool_t* ok) if (fSQL==0) return 0; if (gDebug>2) Info("SQLQuery",cmd); + + fQuerisCounter++; TSQLResult* res = fSQL->Query(cmd); if (ok!=0) *ok = res!=0; @@ -1466,13 +1569,12 @@ TObjArray* TSQLFile::SQLTablesList(const char* searchtable) sqlcmd.Form("SELECT object_name FROM ALL_OBJECTS WHERE object_type='TABLE' and owner='%s'",user.Data()); if (searchtable!=0) { TString table = searchtable; - table.ToUpper(); sqlcmd += Form(" and object_name='%s'",table.Data()); } TSQLResult* tables = SQLQuery(sqlcmd.Data(), 1); if (tables==0) return 0; - + TSQLRow* row = tables->Next(); while (row!=0) { const char* tablename = row->GetField(0); @@ -1515,7 +1617,20 @@ TObjArray* TSQLFile::SQLTableColumns(const char* tablename) TObjArray* res = 0; if (IsOracle()) { - TSQLResult* cols = fSQL->GetColumns(0, tablename, ""); + +// TSQLResult* cols = fSQL->GetColumns(0, tablename, ""); +// if (cols==0) return 0; +// for (Int_t n=0;n<cols->GetFieldCount();n++) { +// TNamed* col = new TNamed(cols->GetFieldName(n), "TYPE?"); +// if (res==0) res = new TObjArray; +// res->Add(col); +// } +// delete cols; + TString sqlcmd; + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT * FROM %s%s%s WHERE ROWNUM<2", + quote, tablename, quote); + TSQLResult* cols = SQLQuery(sqlcmd.Data(), 1); if (cols==0) return 0; for (Int_t n=0;n<cols->GetFieldCount();n++) { TNamed* col = new TNamed(cols->GetFieldName(n), "TYPE?"); @@ -1523,7 +1638,6 @@ TObjArray* TSQLFile::SQLTableColumns(const char* tablename) res->Add(col); } delete cols; - } else { TSQLResult* cols = fSQL->GetColumns(GetDataBaseName(), tablename, ""); @@ -1558,13 +1672,15 @@ Bool_t TSQLFile::SQLTestTable(const char* tablename) } //______________________________________________________________________________ -Int_t TSQLFile::SQLMaximumValue(const char* tablename, const char* columnname) +Long64_t TSQLFile::SQLMaximumValue(const char* tablename, const char* columnname) { // Returns maximum value, found in specified columnname of table tablename // Column type should be numeric if (fSQL==0) return -1; + if (fSQL==0) return -1; + if (gDebug>2) Info("SQLMaximumValue","Requests for %s column %s", tablename, columnname); @@ -1580,16 +1696,16 @@ Int_t TSQLFile::SQLMaximumValue(const char* tablename, const char* columnname) TSQLRow* row = res->Next(); - Int_t maxid = -1; + Long64_t maxid = -1; if (row!=0) if (row->GetField(0)!=0) - maxid = atoi(row->GetField(0)); + maxid = sqlio::atol64(row->GetField(0)); delete row; delete res; if (gDebug>2) - Info("SQLMaximumValue","Result = %d",maxid);; + Info("SQLMaximumValue","Result = %lld",maxid);; return maxid; } @@ -1645,61 +1761,105 @@ Bool_t TSQLFile::SQLRollback() } //______________________________________________________________________________ -void TSQLFile::DeleteKeyFromDB(Int_t keyid) +void TSQLFile::DeleteKeyFromDB(Long64_t keyid) { - // remove key with specified id from keys table - // also removes all objects data, releta to this table - +// remove key with specified id from keys table +// also removes all objects data, related to this table + if (!IsWritable() || (keyid<0) || (fSQL==0)) return; - TString query; + TString sqlcmd; const char* quote = SQLIdentifierQuote(); - query.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%d", - quote, sqlio::ObjectsTable, quote, - quote, SQLKeyIdColumn(), quote, - keyid); - TSQLResult* res = SQLQuery(query.Data(), 2); - if (res==0) return; - TSQLRow* row = res->Next(); - while (row!=0) { - Int_t objid = atoi(row->GetField(1)); - DeleteObjectFromTables(objid); - delete row; - row = res->Next(); + sqlcmd.Form("SELECT MIN(%s%s%s), MAX(%s%s%s) FROM %s%s%s WHERE %s%s%s=%lld", + quote, SQLObjectIdColumn(), quote, + quote, SQLObjectIdColumn(), quote, + quote, sqlio::ObjectsTable, quote, + quote, SQLKeyIdColumn(), quote, keyid); + TSQLResult* res = SQLQuery(sqlcmd.Data(), 2); + TSQLRow* row = res==0 ? 0 : res->Next(); + Long64_t minid(1), maxid(0); + + if ((row!=0) && (row->GetField(0)!=0) && (row->GetField(1)!=0)) { + minid = sqlio::atol64(row->GetField(0)); + maxid = sqlio::atol64(row->GetField(1)); } - + + delete row; delete res; + + // can be that object tables does not include any entry this that keyid + if (minid<=maxid) { + TObjArray* tables = SQLTablesList(); + TIter iter(tables); + TObject* obj = 0; + while ((obj=iter())!=0) { + TString tablename = obj->GetName(); + + if ((tablename.CompareTo(sqlio::KeysTable,TString::kIgnoreCase)==0) || + (tablename.CompareTo(sqlio::ObjectsTable,TString::kIgnoreCase)==0) || + (tablename.CompareTo(sqlio::ConfigTable,TString::kIgnoreCase)==0)) continue; + + TString query; + query.Form("DELETE FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld", + quote, tablename.Data(), quote, + quote, SQLObjectIdColumn(), quote, + minid, maxid); + SQLQuery(query.Data()); + } + + delete tables; + } - query.Form("DELETE FROM %s WHERE %s%s%s=%d", sqlio::ObjectsTable, quote, SQLKeyIdColumn(), quote, keyid); - SQLQuery(query.Data()); + sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, keyid); + SQLQuery(sqlcmd.Data()); - query.Form("DELETE FROM %s WHERE %s%s%s=%d", sqlio::KeysTable, quote, SQLKeyIdColumn(), quote, keyid); - SQLQuery(query.Data()); + sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::KeysTable, quote, quote, SQLKeyIdColumn(), quote, keyid); + SQLQuery(sqlcmd.Data()); IncrementModifyCounter(); } //______________________________________________________________________________ -Bool_t TSQLFile::WriteKeyData(Int_t keyid, Int_t dirid, Int_t objid, const char* keyname, const char* datime, Int_t cycle, const char* clname) +TKeySQL* TSQLFile::FindSQLKey(TDirectory* dir, Long64_t keyid) +{ + // Search for TKeySQL object with specified keyid + + if (dir==0) return 0; + + TIter next(dir->GetListOfKeys()); + TObject* obj = 0; + + while ((obj = next())!=0) { + TKeySQL* key = dynamic_cast<TKeySQL*> (obj); + if (key!=0) + if (key->GetDBKeyId()==keyid) return key; + } + + return 0; +} + +//______________________________________________________________________________ +Bool_t TSQLFile::WriteKeyData(TKeySQL* key) { // add entry into keys table - if (fSQL==0) return kFALSE; + if ((fSQL==0) || (key==0)) return kFALSE; if (!IsTablesExists()) CreateBasicTables(); TString sqlcmd; const char* valuequote = SQLValueQuote(); const char* quote = SQLIdentifierQuote(); - - sqlcmd.Form("INSERT INTO %s%s%s VALUES (%d, %d, %d, %s%s%s, %s%s%s, %d, %s%s%s)", + + sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %lld, %lld, %s%s%s, %s%s%s, %s%s%s, %d, %s%s%s)", quote, sqlio::KeysTable, quote, - keyid, dirid, objid, - valuequote, keyname, valuequote, - valuequote, datime, valuequote, - cycle, - valuequote, clname, valuequote); + key->GetDBKeyId(), key->GetDBDirId(), key->GetDBObjId(), + valuequote, key->GetName(), valuequote, + valuequote, key->GetTitle(), valuequote, + valuequote, key->GetDatime().AsSQLString(), valuequote, + key->GetCycle(), + valuequote, key->GetClassName(), valuequote); Bool_t ok = kTRUE; @@ -1711,11 +1871,37 @@ Bool_t TSQLFile::WriteKeyData(Int_t keyid, Int_t dirid, Int_t objid, const char* } //______________________________________________________________________________ -Int_t TSQLFile::DefineNextKeyId() +Bool_t TSQLFile::UpdateKeyData(TKeySQL* key) +{ + if ((fSQL==0) || (key==0)) return kFALSE; + + TString sqlcmd; + const char* valuequote = SQLValueQuote(); + const char* quote = SQLIdentifierQuote(); + + sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s, %s=%s WHERE %s%s%s=%lld", + quote, sqlio::KeysTable, quote, + sqlio::KT_Name, valuequote, key->GetName(), valuequote, + sqlio::KT_Title, valuequote, key->GetTitle(), valuequote, + sqlio::KT_Datetime, valuequote, key->GetDatime().AsSQLString(), valuequote, + sqlio::KT_Cycle, key->GetCycle(), + quote, SQLKeyIdColumn(), quote, key->GetDBKeyId()); + + Bool_t ok = kTRUE; + + SQLQuery(sqlcmd.Data(), 0, &ok); + + if (ok) IncrementModifyCounter(); + + return ok; +} + +//______________________________________________________________________________ +Long64_t TSQLFile::DefineNextKeyId() { // Returns next possible key identifier - Int_t max = -1; + Long64_t max = -1; if (SQLTestTable(sqlio::KeysTable)) max = SQLMaximumValue(sqlio::KeysTable, SQLKeyIdColumn()); @@ -1830,7 +2016,7 @@ Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bo } sqlcmd += ")"; - if (fTablesType.Length()>0) { + if ((fTablesType.Length()>0) && IsMySQL()) { sqlcmd +=" TYPE="; sqlcmd += fTablesType; } @@ -1858,7 +2044,7 @@ Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bo sqlio::BT_Field, SQLSmallTextType(), sqlio::BT_Value, SQLSmallTextType()); - if (fTablesType.Length()>0) { + if ((fTablesType.Length()>0) && IsMySQL()) { sqlcmd +=" TYPE="; sqlcmd += fTablesType; } @@ -1910,16 +2096,16 @@ Bool_t TSQLFile::VerifyLongStringTable() } //______________________________________________________________________________ -TString TSQLFile::CodeLongString(Int_t objid, Int_t strid) +TString TSQLFile::CodeLongString(Long64_t objid, Int_t strid) { // produces id which will be placed in column instead of string itself TString res; - res.Form("%s %d %s %d %s", sqlio::LongStrPrefix, objid, sqlio::LongStrPrefix, strid, sqlio::LongStrPrefix); + res.Form("%s %lld %s %d %s", sqlio::LongStrPrefix, objid, sqlio::LongStrPrefix, strid, sqlio::LongStrPrefix); return res; } //______________________________________________________________________________ -Int_t TSQLFile::IsLongStringCode(const char* value, Int_t objid) +Int_t TSQLFile::IsLongStringCode(Long64_t objid, const char* value) { // checks if this is long string code // returns 0, if not or string id @@ -1948,13 +2134,14 @@ Int_t TSQLFile::IsLongStringCode(const char* value, Int_t objid) if ((*value==0) || (strcmp(value, sqlio::LongStrPrefix)!=0)) return 0; - if (atoi(s_objid.Data())!=objid) return 0; + Long64_t objid2 = sqlio::atol64(s_objid.Data()); + if (objid2!=objid) return 0; return atoi(s_strid.Data()); } //______________________________________________________________________________ -Bool_t TSQLFile::GetLongString(Int_t objid, Int_t strid, TString& value) +Bool_t TSQLFile::GetLongString(Long64_t objid, Int_t strid, TString& value) { // returns value of string, extracted from special table, // where long strings are stored @@ -1963,7 +2150,7 @@ Bool_t TSQLFile::GetLongString(Int_t objid, Int_t strid, TString& value) TString cmd; const char* quote = SQLIdentifierQuote(); - cmd.Form("SELECT %s FROM %s%s%s WHERE %s%s%s=%d AND %s%s%s=%d", + cmd.Form("SELECT %s FROM %s%s%s WHERE %s%s%s=%lld AND %s%s%s=%d", sqlio::ST_Value, quote, sqlio::StringsTable, quote, quote, SQLObjectIdColumn(), quote, objid, @@ -1982,7 +2169,7 @@ Bool_t TSQLFile::GetLongString(Int_t objid, Int_t strid, TString& value) } //______________________________________________________________________________ -Int_t TSQLFile::VerifyObjectTable() +Long64_t TSQLFile::VerifyObjectTable() { // Checks that objects table is exists // If not, table will be created @@ -1990,7 +2177,7 @@ Int_t TSQLFile::VerifyObjectTable() if (fSQL==0) return -1; - Int_t maxid = -1; + Long64_t maxid = -1; if (gDebug>2) Info("VerifyObjectTable", "Checks if object table is there"); @@ -2000,14 +2187,14 @@ Int_t TSQLFile::VerifyObjectTable() else { TString sqlcmd; const char* quote = SQLIdentifierQuote(); - sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)", + sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s%s%s %s, %s%s%s %s)", quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, SQLIntType(), quote, SQLObjectIdColumn(), quote, SQLIntType(), - sqlio::OT_Class, SQLSmallTextType(), - sqlio::OT_Version, SQLIntType()); + quote, sqlio::OT_Class, quote, SQLSmallTextType(), + quote, sqlio::OT_Version, quote, SQLIntType()); - if (fTablesType.Length()>0) { + if ((fTablesType.Length()>0) && IsMySQL()) { sqlcmd +=" TYPE="; sqlcmd += fTablesType; } @@ -2027,28 +2214,7 @@ Int_t TSQLFile::VerifyObjectTable() } //______________________________________________________________________________ -TString TSQLFile::SetObjectDataCmd(Int_t keyid, Int_t objid, TClass* cl) -{ - // produces SQL query to set object data - // command will be submited later - - TString cmd; - const char* quote = SQLIdentifierQuote(); - const char* valuequote = SQLValueQuote(); - cmd.Form("INSERT INTO %s%s%s (%s%s%s, %s%s%s, %s, %s) VALUES (%d, %d, %s%s%s, %d)", - quote, sqlio::ObjectsTable, quote, - quote, SQLKeyIdColumn(), quote, - quote, SQLObjectIdColumn(), quote, - sqlio::OT_Class, - sqlio::OT_Version, - keyid, objid, - valuequote, cl->GetName(), valuequote, - cl->GetClassVersion()); - return cmd; -} - -//______________________________________________________________________________ -Bool_t TSQLFile::GetObjectData(Int_t objid, TString& clname, Version_t &version) +Bool_t TSQLFile::SQLObjectInfo(Long64_t objid, TString& clname, Version_t &version) { // Read from objects table data for specified objectid @@ -2056,8 +2222,9 @@ Bool_t TSQLFile::GetObjectData(Int_t objid, TString& clname, Version_t &version) TString sqlcmd; const char* quote = SQLIdentifierQuote(); - sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%d", - sqlio::OT_Class, sqlio::OT_Version, + sqlcmd.Form("SELECT %s%s%s, %s%s%s FROM %s%s%s WHERE %s%s%s=%lld", + quote, sqlio::OT_Class, quote, + quote, sqlio::OT_Version, quote, quote, sqlio::ObjectsTable, quote, quote, SQLObjectIdColumn(), quote, objid); TSQLResult* res = SQLQuery(sqlcmd.Data(), 1); @@ -2074,69 +2241,154 @@ Bool_t TSQLFile::GetObjectData(Int_t objid, TString& clname, Version_t &version) } //______________________________________________________________________________ -TSQLObjectData* TSQLFile::GetObjectClassData(Int_t objid, TSQLClassInfo* sqlinfo) +TObjArray* TSQLFile::SQLObjectsInfo(Long64_t keyid) { - // Get data for specified object from particular class table - // Returns TSQLObjectData object, which contains one row from - // normal class table and data from _streamer_ table. - // TSQLObjectData object used later in TBufferSQL2 to unstream object +// Produce array of TSQLObjectInfo objects for all objects, belong to that key +// Array should be deleted by calling function afterwards + if (fSQL==0) return 0; - if ((fSQL==0) || (objid<0) || (sqlinfo==0)) return 0; + TString sqlcmd; + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT %s%s%s, %s%s%s, %s%s%s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", + quote, SQLObjectIdColumn(), quote, + quote, sqlio::OT_Class, quote, + quote, sqlio::OT_Version, quote, + quote, sqlio::ObjectsTable, quote, + quote, SQLKeyIdColumn(), quote, keyid, + quote, SQLObjectIdColumn(), quote); + TSQLResult* res = SQLQuery(sqlcmd.Data(), 1); + if (res==0) return 0; + + TObjArray* arr = 0; + TSQLRow* row = 0; + while ((row = res->Next()) != 0) { + Long64_t objid = atoi(row->GetField(0)); + const char* clname = row->GetField(1); + Int_t version = atoi(row->GetField(2)); + + TSQLObjectInfo* info = new TSQLObjectInfo(objid, clname, version); + if (arr==0) arr = new TObjArray(); + arr->Add(info); + + delete row; + } + delete res; + return arr; +} - if (gDebug>1) - Info("GetObjectClassData","Request for %s", sqlinfo->GetName()); +//______________________________________________________________________________ +TSQLResult* TSQLFile::GetNormalClassData(Long64_t objid, TSQLClassInfo* sqlinfo) +{ +// Method return request result for specified objid from normal classtable + if (!sqlinfo->IsClassTableExist()) return 0; + TString sqlcmd; const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%lld", + quote, sqlinfo->GetClassTableName(), quote, + quote, SQLObjectIdColumn(), quote, objid); + return SQLQuery(sqlcmd.Data(), 2); +} - TSQLResult *classdata = 0, *blobdata = 0; +//______________________________________________________________________________ +TSQLResult* TSQLFile::GetNormalClassDataAll(Long64_t minobjid, Long64_t maxobjid, TSQLClassInfo* sqlinfo) +{ + if (!sqlinfo->IsClassTableExist()) return 0; + TString sqlcmd; + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld ORDER BY %s%s%s", + quote, sqlinfo->GetClassTableName(), quote, + quote, SQLObjectIdColumn(), quote, minobjid, maxobjid, + quote, SQLObjectIdColumn(), quote); + return SQLQuery(sqlcmd.Data(), 2); +} - if (sqlinfo->IsClassTableExist()) { - TString sqlcmd; - sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s=%d", - quote, sqlinfo->GetClassTableName(), quote, - quote, SQLObjectIdColumn(), quote, objid); - classdata = SQLQuery(sqlcmd.Data(), 2); - } +//______________________________________________________________________________ +TSQLResult* TSQLFile::GetBlobClassData(Long64_t objid, TSQLClassInfo* sqlinfo) +{ +// Method return request results for specified objid from _streamer_ classtable if (sqlinfo->IsRawTableExist()) { TString sqlcmd; - sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%d ORDER BY %s%s%s", + const char* quote = SQLIdentifierQuote(); + sqlcmd.Form("SELECT %s, %s FROM %s%s%s WHERE %s%s%s=%lld ORDER BY %s%s%s", sqlio::BT_Field, sqlio::BT_Value, quote, sqlinfo->GetRawTableName(), quote, quote, SQLObjectIdColumn(), quote, objid, quote, SQLRawIdColumn(), quote); - blobdata = SQLQuery(sqlcmd.Data(), 2); + return SQLQuery(sqlcmd.Data(), 2); } - - return new TSQLObjectData(sqlinfo, objid, classdata, blobdata); + + return 0; } //______________________________________________________________________________ -void TSQLFile::DeleteObjectFromTables(Int_t objid) +TSQLObjectData* TSQLFile::GetObjectClassData(Long64_t objid, TSQLClassInfo* sqlinfo) { - // delete object with specified id from all tables + // Get data for specified object from particular class table + // Returns TSQLObjectData object, which contains one row from + // normal class table and data from _streamer_ table. + // TSQLObjectData object used later in TBufferSQL2 to unstream object - TObjArray* tables = SQLTablesList(); - if (tables==0) return; + if ((fSQL==0) || (objid<0) || (sqlinfo==0)) return 0; - const char* quote = SQLIdentifierQuote(); + if (gDebug>1) + Info("GetObjectClassData","Request for %s id = %lld", sqlinfo->GetName(), objid); - TIter iter(tables); - TObject* obj = 0; - while ((obj=iter())!=0) { - TString tablename = obj->GetName(); + TSQLResult *classdata = GetNormalClassData(objid, sqlinfo); + + TSQLResult *blobdata = GetBlobClassData(objid, sqlinfo); + + if (gDebug>3) + Info("GetObjectClassData","normal = %x blobdata = %x", classdata, blobdata); - if ((tablename.CompareTo(sqlio::KeysTable,TString::kIgnoreCase)==0) || - (tablename.CompareTo(sqlio::ObjectsTable,TString::kIgnoreCase)==0)) continue; + return new TSQLObjectData(sqlinfo, objid, classdata, 0, blobdata); +} - TString query; - query.Form("DELETE FROM %s WHERE %s%s%s=%d", tablename.Data(), - quote, SQLObjectIdColumn(), quote, objid); - SQLQuery(query.Data()); +//______________________________________________________________________________ +Long64_t TSQLFile::StoreObjectInTables(Long64_t keyid, const void* obj, const TClass* cl) +{ + // Store object in database. Return stored object id or -1 if error + + if (fSQL==0) return -1; - } + Long64_t objid = VerifyObjectTable(); + if (objid<=0) objid = 1; else objid++; - delete tables; + TBufferSQL2 buffer(TBuffer::kWrite, this); + + TSQLStructure* s = buffer.SqlWriteAny(obj, cl, objid); + + if ((buffer.GetErrorFlag()>0) && (s!=0)) { + Error("StoreObjectInTables","Cannot convert object data to TSQLStructure"); + objid = -1; + } else { + TObjArray cmds; + // here tables may be already created, therefore + // it should be protected by transactions operations + if (!s->ConvertToTables(this, keyid, &cmds)) { + Error("StoreObjectInTables","Cannot convert to SQL statements"); + objid = -1; + } else { + Bool_t needcommit = kFALSE; + + if (GetUseTransactions()==kTransactionsAuto) { + SQLStartTransaction(); + needcommit = kTRUE; + } + + if (!SQLApplyCommands(&cmds)) { + Error("StoreObject","Cannot correctly store object data in database"); + objid = -1; + if (needcommit) SQLRollback(); + } else { + if (needcommit) SQLCommit(); + } + } + cmds.Delete(); + } + + return objid; } //______________________________________________________________________________ diff --git a/sql/src/TSQLObjectData.cxx b/sql/src/TSQLObjectData.cxx index 8ad05672590..38114f62ace 100644 --- a/sql/src/TSQLObjectData.cxx +++ b/sql/src/TSQLObjectData.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLObjectData.cxx,v 1.2 2005/11/22 20:42:36 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLObjectData.cxx,v 1.3 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -27,14 +27,43 @@ #include "TSQLRow.h" #include "TSQLResult.h" #include "TSQLClassInfo.h" +#include "TSQLStructure.h" + +ClassImp(TSQLObjectInfo) + +//________________________________________________________________________ +TSQLObjectInfo::TSQLObjectInfo() : + TObject(), + fObjId(0), + fClassName(), + fVersion(0) +{ +} + +//________________________________________________________________________ +TSQLObjectInfo::TSQLObjectInfo(Long64_t objid, const char* classname, Version_t version) : + TObject(), + fObjId(objid), + fClassName(classname), + fVersion(version) +{ +} + +//________________________________________________________________________ +TSQLObjectInfo::~TSQLObjectInfo() +{ +} + + ClassImp(TSQLObjectData) //________________________________________________________________________ - TSQLObjectData::TSQLObjectData() : +TSQLObjectData::TSQLObjectData() : TObject(), fInfo(0), fObjId(0), + fOwner(kFALSE), fClassData(0), fBlobData(0), fLocatedColumn(-1), @@ -52,16 +81,18 @@ ClassImp(TSQLObjectData) //______________________________________________________________________________ TSQLObjectData::TSQLObjectData(TSQLClassInfo* sqlinfo, - Int_t objid, + Long64_t objid, TSQLResult* classdata, + TSQLRow* classrow, TSQLResult* blobdata) : TObject(), fInfo(sqlinfo), fObjId(objid), + fOwner(kFALSE), fClassData(classdata), fBlobData(blobdata), fLocatedColumn(-1), - fClassRow(0), + fClassRow(classrow), fBlobRow(0), fLocatedField(0), fLocatedValue(0), @@ -72,11 +103,13 @@ TSQLObjectData::TSQLObjectData(TSQLClassInfo* sqlinfo, { // normal contrsuctor, - if (fClassData!=0) + // take ownership if no special row from data pool is provided + if ((fClassData!=0) && (fClassRow==0)) { + fOwner = kTRUE; fClassRow = fClassData->Next(); + } if (fBlobData!=0) fBlobRow = fBlobData->Next(); - } //______________________________________________________________________________ @@ -84,9 +117,9 @@ TSQLObjectData::~TSQLObjectData() { // destructor of TSQLObjectData object + if ((fClassData!=0) && fOwner) delete fClassData; if (fClassRow!=0) delete fClassRow; if (fBlobRow!=0) delete fBlobRow; - if (fClassData!=0) delete fClassData; if (fBlobData!=0) delete fBlobData; if (fUnpack!=0) { fUnpack->Delete(); delete fUnpack; } } @@ -281,3 +314,73 @@ Bool_t TSQLObjectData::PrepareForRawData() return kTRUE; } +//=================================================================================== + +ClassImp(TSQLObjectDataPool); + +//______________________________________________________________________________ +TSQLObjectDataPool::TSQLObjectDataPool() : + TObject(), + fInfo(0), + fClassData(0), + fIsMoreRows(kTRUE), + fRowsPool(0) +{ +} + +//______________________________________________________________________________ +TSQLObjectDataPool::TSQLObjectDataPool(TSQLClassInfo* info, TSQLResult* data) : + TObject(), + fInfo(info), + fClassData(data), + fIsMoreRows(kTRUE), + fRowsPool(0) +{ +} + +//______________________________________________________________________________ +TSQLObjectDataPool::~TSQLObjectDataPool() +{ + if (fClassData!=0) delete fClassData; + if (fRowsPool!=0) { + fRowsPool->Delete(); + delete fRowsPool; + } +} + +//______________________________________________________________________________ +TSQLRow* TSQLObjectDataPool::GetObjectRow(Long64_t objid) +{ + if (fClassData==0) return 0; + + Long64_t rowid; + + if (fRowsPool!=0) { + TObjLink* link = fRowsPool->FirstLink(); + while (link!=0) { + TSQLRow* row = (TSQLRow*) link->GetObject(); + rowid = sqlio::atol64(row->GetField(0)); + if (rowid==objid) { + fRowsPool->Remove(link); + return row; + } + + link = link->Next(); + } + } + + while (fIsMoreRows) { + TSQLRow* row = fClassData->Next(); + if (row==0) + fIsMoreRows = kFALSE; + else { + rowid = sqlio::atol64(row->GetField(0)); + if (rowid==objid) return row; + if (fRowsPool==0) fRowsPool = new TList(); + fRowsPool->Add(row); + } + } + + return 0; +} + diff --git a/sql/src/TSQLStructure.cxx b/sql/src/TSQLStructure.cxx index 16a0d1364fd..87466a35bc9 100644 --- a/sql/src/TSQLStructure.cxx +++ b/sql/src/TSQLStructure.cxx @@ -1,4 +1,4 @@ -// @(#)root/sql:$Name: $:$Id: TSQLStructure.cxx,v 1.6 2005/12/01 16:30:43 pcanal Exp $ +// @(#)root/sql:$Name: $:$Id: TSQLStructure.cxx,v 1.7 2005/12/07 14:59:57 rdm Exp $ // Author: Sergey Linev 20/11/2005 /************************************************************************* @@ -24,6 +24,7 @@ #include "TSQLStructure.h" #include "Riostream.h" +#include "TMap.h" #include "TClass.h" #include "TStreamerInfo.h" #include "TStreamerElement.h" @@ -33,12 +34,14 @@ #include "TSQLFile.h" #include "TSQLClassInfo.h" #include "TSQLObjectData.h" +#include "TBufferSQL2.h" namespace sqlio { const Int_t Ids_NullPtr = 0; // used to identify NULL pointer in tables const Int_t Ids_RootDir = 0; // dir:id, used for keys stored in root directory. - const Int_t Ids_StreamerInfos = 0; // keyid used to store StreamerInfos in ROOT directory - const Int_t Ids_FirstKey = 1; // first key id, which is used in KeysTable (beside streamer info or something else) + const Int_t Ids_TSQLFile = 0; // keyid for TSQLFile entry in keys list + const Int_t Ids_StreamerInfos = 1; // keyid used to store StreamerInfos in ROOT directory + const Int_t Ids_FirstKey =10; // first key id, which is used in KeysTable (beside streamer info or something else) const Int_t Ids_FirstObject = 1; // first object id, allowed in object tables const char* ObjectRef = "ObjectRef"; @@ -86,9 +89,14 @@ namespace sqlio { // colummns in Keys table const char* KT_Name = "Name"; + const char* KT_Title = "Title"; const char* KT_Datetime = "Datime"; const char* KT_Cycle = "Cycle"; const char* KT_Class = "Class"; + + const char* DT_Create = "CreateDatime"; + const char* DT_Modified = "ModifiedDatime"; + const char* DT_UUID = "UUID"; // colummns in Objects table const char* OT_Class = "Class"; @@ -118,6 +126,28 @@ namespace sqlio { //________________________________________________________________________ +#ifdef R__VISUAL_CPLUSPLUS +#define FLong64 "%I64d" +#define FULong64 "%I64u" +#else +#ifdef R__B64 +#define FLong64 "%ld" +#define FULong64 "%lu" +#else +#define FLong64 "%lld" +#define FULong64 "%llu" +#endif +#endif + +Long64_t sqlio::atol64(const char* value) +{ + if ((value==0) || (*value==0)) return 0; + Long64_t res = 0; + sscanf(value, FLong64, &res); + return res; +} + + ClassImp(TSQLColumnData) //______________________________________________________________________________ @@ -147,7 +177,7 @@ TSQLColumnData::TSQLColumnData(const char* name, } //________________________________________________________________________ -TSQLColumnData::TSQLColumnData(const char* name, Int_t value) : +TSQLColumnData::TSQLColumnData(const char* name, Long64_t value) : TObject(), fName(name), fType("INT"), @@ -156,7 +186,7 @@ TSQLColumnData::TSQLColumnData(const char* name, Int_t value) : { // constructs TSQLColumnData object for integer column - fValue.Form("%d",value); + fValue.Form("%lld",value); } //________________________________________________________________________ @@ -191,6 +221,10 @@ TSQLStructure::~TSQLStructure() if (GetType()==kSqlObjectData) { TSQLObjectData* objdata = (TSQLObjectData*) fPointer; delete objdata; + } else + if (GetType()==kSqlCustomElement) { + TStreamerElement* elem = (TStreamerElement*) fPointer; + delete elem; } } @@ -211,22 +245,22 @@ TSQLStructure* TSQLStructure::GetChild(Int_t n) const } //________________________________________________________________________ -void TSQLStructure::SetObjectRef(Int_t refid, const TClass* cl) +void TSQLStructure::SetObjectRef(Long64_t refid, const TClass* cl) { // set structure type as kSqlObject fType = kSqlObject; - fValue.Form("%d",refid); + fValue.Form("%lld",refid); fPointer = cl; } //________________________________________________________________________ -void TSQLStructure::SetObjectPointer(Int_t ptrid) +void TSQLStructure::SetObjectPointer(Long64_t ptrid) { // set structure type as kSqlPointer fType = kSqlPointer; - fValue.Form("%d",ptrid); + fValue.Form("%lld",ptrid); } //________________________________________________________________________ @@ -268,6 +302,21 @@ void TSQLStructure::SetStreamerElement(const TStreamerElement* elem, Int_t numbe fArrayIndex = number; } +//________________________________________________________________________ +void TSQLStructure::SetCustomClass(const TClass* cl, Version_t version) +{ + fType = kSqlCustomClass; + fPointer = (void*) cl; + fArrayIndex = version; +} + +//________________________________________________________________________ +void TSQLStructure::SetCustomElement(TStreamerElement* elem) +{ + fType = kSqlCustomElement; + fPointer = elem; +} + //________________________________________________________________________ void TSQLStructure::SetValue(const char* value, const char* tname) { @@ -344,7 +393,7 @@ TStreamerElement* TSQLStructure::GetElement() const { // return TStremerElement* if type is kSqlElement - return (fType==kSqlElement) ? (TStreamerElement*) fPointer : 0; + return (fType==kSqlElement) || (fType==kSqlCustomElement) ? (TStreamerElement*) fPointer : 0; } //________________________________________________________________________ @@ -363,6 +412,35 @@ const char* TSQLStructure::GetValueType() const return (fType==kSqlValue) ? (const char*) fPointer : 0; } +//________________________________________________________________________ +TClass* TSQLStructure::GetCustomClass() const +{ + return (fType==kSqlCustomClass) ? (TClass*) fPointer : 0; +} + +//________________________________________________________________________ +Version_t TSQLStructure::GetCustomClassVersion() const +{ + return (fType==kSqlCustomClass) ? fArrayIndex : 0; +} + +//________________________________________________________________________ +Bool_t TSQLStructure::GetClassInfo(TClass* &cl, Version_t &version) +{ + if (GetType()==kSqlStreamerInfo) { + TStreamerInfo* info = GetStreamerInfo(); + if (info==0) return kFALSE; + cl = info->GetClass(); + version = info->GetClassVersion(); + } else + if (GetType()==kSqlCustomClass) { + cl = GetCustomClass(); + version = GetCustomClassVersion(); + } else + return kFALSE; + return kTRUE; +} + //________________________________________________________________________ const char* TSQLStructure::GetValue() const { @@ -405,7 +483,7 @@ void TSQLStructure::AddValue(const char* value, const char* tname) } //________________________________________________________________________ -Int_t TSQLStructure::DefineObjectId() +Long64_t TSQLStructure::DefineObjectId(Bool_t recursive) { // defines current object id, to which this structure belong // make life complicated, because some objects do not get id @@ -413,56 +491,22 @@ Int_t TSQLStructure::DefineObjectId() TSQLStructure* curr = this; while (curr!=0) { - // workaround to store object id in element structure - if ((curr->GetType()==kSqlElement) || + if ((curr->GetType()==kSqlObject) || + // workaround to store object id in element structure + (curr->GetType()==kSqlElement) || + (curr->GetType()==kSqlCustomElement) || + (curr->GetType()==kSqlCustomClass) || (curr->GetType()==kSqlStreamerInfo)) { const char* value = curr->GetValue(); - if ((value!=0) && (strlen(value)>0)) return atoi(value); + if ((value!=0) && (strlen(value)>0)) + return sqlio::atol64(value); } - if (curr->GetType()==kSqlObject) - return atoi(curr->GetValue()); - curr = curr->GetParent(); + curr = recursive ? curr->GetParent() : 0; } return -1; } -//________________________________________________________________________ -Bool_t TSQLStructure::IsClonesArray() -{ - // defines if this structure below node, which correspondes to - // clones array. Used to force convertion of all data into raw format - - // disable any special handling of TClonesArray - - return kFALSE; - - TSQLStructure* curr = this; - while (curr!=0) { - if (curr->GetType()==kSqlObject) - return curr->GetObjectClass()==TClonesArray::Class(); - - // workaround for nested TClonesArray - if ((curr->GetType()==kSqlElement) || - (curr->GetType()==kSqlStreamerInfo)) { - const char* value = curr->GetValue(); - // check that element has object id and one can analyse it class - if ((value!=0) && (strlen(value)>0)) { - TStreamerInfo* info = GetStreamerInfo(); - if (info!=0) - return info->GetClass()==TClonesArray::Class(); - TStreamerElement* elem = GetElement(); - if (elem!=0) - return elem->GetClassPointer()==TClonesArray::Class(); - return kFALSE; - } - } - - curr = curr->GetParent(); - } - return kFALSE; -} - //________________________________________________________________________ void TSQLStructure::SetObjectData(TSQLObjectData* objdata) { @@ -523,6 +567,7 @@ void TSQLStructure::PrintLevel(Int_t level) const cout << "Class: " << info->GetName(); break; } + case kSqlCustomElement: case kSqlElement: { const TStreamerElement* elem = (const TStreamerElement*) fPointer; cout << "Member: " << elem->GetName(); @@ -539,6 +584,11 @@ void TSQLStructure::PrintLevel(Int_t level) const if (fValue.Length()>0) cout << " sz = " << fValue; break; } + case kSqlCustomClass: { + TClass* cl = (TClass*) fPointer; + cout << "CustomClass: " << cl->GetName() << " ver = " << fValue; + break; + } default: cout << "Unknown type"; } @@ -618,6 +668,37 @@ const char* TSQLStructure::GetSimpleTypeName(Int_t typ) return 0; } +// ====================================================================== + +class TSqlCmdsBuffer : public TObject { + +public: + TSqlCmdsBuffer(TSQLClassInfo* info = 0) : + TObject(), + fInfo(info) + { + } + + virtual ~TSqlCmdsBuffer() + { + fNormCmds.Delete(); + fBlobCmds.Delete(); + } + + void AddValues(Bool_t isnorm, const char* values) + { + TObjString* str = new TObjString(values); + if (isnorm) fNormCmds.Add(str); + else fBlobCmds.Add(str); + } + + TSQLClassInfo* fInfo; + TObjArray fNormCmds; + TObjArray fBlobCmds; +}; + + + //________________________________________________________________________ class TSqlRegistry : public TObject { @@ -629,28 +710,38 @@ public: fLastObjId(-1), fCmds(0), fFirstObjId(0), - fRegCmds(), - fCurrentObjId(), + fCurrentObjId(0), fCurrentObjClass(0), - fLastLongStrId(0) + fLastLongStrId(0), + fPool(), + fLongStrValues(), + fRegValues() { } TSQLFile* f; - Int_t fKeyId; - Int_t fLastObjId; + Long64_t fKeyId; + Long64_t fLastObjId; TObjArray* fCmds; - Int_t fFirstObjId; - TObjArray fRegCmds; + Long64_t fFirstObjId; - TString fCurrentObjId; + Long64_t fCurrentObjId; TClass* fCurrentObjClass; Int_t fLastLongStrId; + + TMap fPool; + TObjArray fLongStrValues; + TObjArray fRegValues; - virtual ~TSqlRegistry() {} + virtual ~TSqlRegistry() + { + fPool.DeleteValues(); + fLongStrValues.Delete(); + fRegValues.Delete(); + } - Int_t GetNextObjId() { return ++fLastObjId; } + Long64_t GetNextObjId() { return ++fLastObjId; } void AddSqlCmd(const char* query) { @@ -658,25 +749,85 @@ public: if (fCmds==0) fCmds = new TObjArray; fCmds->Add(new TObjString(query)); } - - void AddBrackets(TString& s, const char* quote) + + TSqlCmdsBuffer* GetCmdsBuffer(TSQLClassInfo* sqlinfo) { - // add brackets to the string value - if (strcmp(quote,"\"")==0) s.ReplaceAll("\"","\\\""); - else s.ReplaceAll("'","''"); - s.Prepend(quote); - s.Append(quote); + if (sqlinfo==0) return 0; + TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo); + if (buf==0) { + buf = new TSqlCmdsBuffer(sqlinfo); + fPool.Add(sqlinfo, buf); + } + return buf; } + + void ConvertSqlValues(TObjArray& values, const char* tablename) + { + // this function transforms array of values for one table + // to SQL command. For MySQL one INSERT querie can + // contain data for more than one row + + if ((values.GetLast()<0) || (tablename==0)) return; + + Bool_t canbelong = f->IsMySQL(); + + Int_t maxsize = 50000; + TString sqlcmd(maxsize), value, onecmd, cmdmask; - void AddRegCmd(const char* cmd, Int_t objid) + const char* quote = f->SQLIdentifierQuote(); + + TIter iter(&values); + TObject* cmd = 0; + while ((cmd = iter())!=0) { + + if (sqlcmd.Length()==0) + sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", + quote, tablename, quote, cmd->GetName()); + else { + sqlcmd+=", ("; + sqlcmd += cmd->GetName(); + sqlcmd+=")"; + } + + if (!canbelong || (sqlcmd.Length()>maxsize*0.9)) { + AddSqlCmd(sqlcmd.Data()); + sqlcmd = ""; + } + } + + if (sqlcmd.Length()>0) AddSqlCmd(sqlcmd.Data()); + } + + void ConvertPoolValues() { - // add special command to register object in objects table + TSQLClassInfo* sqlinfo = 0; + TIter iter(&fPool); + while ((sqlinfo = (TSQLClassInfo*) iter())!=0) { + TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo); + if (buf==0) continue; + ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName()); + ConvertSqlValues(buf->fBlobCmds, sqlinfo->GetRawTableName()); + } + + ConvertSqlValues(fLongStrValues, sqlio::StringsTable); + ConvertSqlValues(fRegValues, sqlio::ObjectsTable); + } - Int_t indx = objid-fFirstObjId; - if (indx<0) - Error("AddRegCmd","Soemthing wrong"); - else - fRegCmds.AddAtAndExpand(new TObjString(cmd), indx); + + void AddRegCmd(Long64_t objid, TClass* cl) + { + Long64_t indx = objid-fFirstObjId; + if (indx<0) { + Error("AddRegCmd","Something wrong with objid = %lld", objid); + return; + } + const char* valuequote = f->SQLValueQuote(); + TString cmd; + cmd.Form("%lld, %lld, %s%s%s, %d", + fKeyId, objid, + valuequote, cl->GetName(), valuequote, + cl->GetClassVersion()); + fRegValues.AddAtAndExpand(new TObjString(cmd), indx); } Int_t AddLongString(const char* strvalue) @@ -688,136 +839,76 @@ public: Int_t strid = ++fLastLongStrId; TString value = strvalue; const char* valuequote = f->SQLValueQuote(); - const char* quote = f->SQLIdentifierQuote(); - AddBrackets(value, valuequote); + TSQLStructure::AddStrBrackets(value, valuequote); TString cmd; - cmd.Form("INSERT INTO %s%s%s VALUES (%s, %d, %s)", - quote, sqlio::StringsTable, quote, - fCurrentObjId.Data(), strid, value.Data()); - AddSqlCmd(cmd.Data()); - return strid; - } + cmd.Form("%lld, %d, %s", fCurrentObjId, strid, value.Data()); - void ConvertRawOracle(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid) - { - // special code for Oracle, which does not allow multiple INSERT syntax - // therefore eachline in raw table should be inseretd with - // separate INSERT command + fLongStrValues.Add(new TObjString(cmd)); - TString sqlcmd, value; - TIter iter(blobs); - TNamed* cmd = 0; - const char* valuequote = f->SQLValueQuote(); - const char* quote = f->SQLIdentifierQuote(); - while ((cmd = (TNamed*)iter())!=0) { - value = cmd->GetTitle(); - AddBrackets(value, valuequote); - - sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s, %d, %s%s%s, %s)", - quote, sqlinfo->GetRawTableName(), quote, - fCurrentObjId.Data(), - rawid++, - valuequote, cmd->GetName(), valuequote, - value.Data()); - AddSqlCmd(sqlcmd.Data()); - } + return strid; } - + void ConvertBlobs(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid) { - // this function transforms blob pairs (field, value) to SQL command - // one command includes more than one row to improve speed - - if (f->IsOracle()) { - ConvertRawOracle(blobs, sqlinfo, rawid); - return; - } - - Int_t maxsize = 50000; - TString sqlcmd(maxsize), value, onecmd, cmdmask; + TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); + if (buf==0) return; + + TString value, onecmd, cmdmask; const char* valuequote = f->SQLValueQuote(); - const char* quote = f->SQLIdentifierQuote(); - cmdmask.Form("(%s, %s, %s%s%s, %s)", fCurrentObjId.Data(), "%d", valuequote, "%s", valuequote, "%s"); + cmdmask.Form("%lld, %s, %s%s%s, %s", fCurrentObjId, "%d", valuequote, "%s", valuequote, "%s"); TIter iter(blobs); TNamed* cmd = 0; while ((cmd = (TNamed*)iter())!=0) { value = cmd->GetTitle(); - AddBrackets(value, valuequote); + TSQLStructure::AddStrBrackets(value, valuequote); onecmd.Form(cmdmask.Data(), rawid++, cmd->GetName(), value.Data()); - - if (sqlcmd.Length()==0) - sqlcmd.Form("INSERT INTO %s%s%s VALUES %s", - quote, sqlinfo->GetRawTableName(), quote, - onecmd.Data()); - else { - sqlcmd+=", "; - sqlcmd += onecmd; - } - - if (sqlcmd.Length()>maxsize*0.9) { - AddSqlCmd(sqlcmd.Data()); - sqlcmd = ""; - } + buf->AddValues(kFALSE, onecmd.Data()); } - - if (sqlcmd.Length()>0) AddSqlCmd(sqlcmd.Data()); } - - void InsertToNormalTable(TObjArray* columns, const char* tablename) + + void InsertToNormalTable(TObjArray* columns, TSQLClassInfo* sqlinfo) { // produce SQL query to insert object data into normal table - TString names, values; - TIter iter(columns); TSQLColumnData* col; - const char* quote = f->SQLIdentifierQuote(); const char* valuequote = f->SQLValueQuote(); - Bool_t forcequote = f->IsOracle(); + TString values; + + Bool_t first = kTRUE; while ((col=(TSQLColumnData*)iter())!=0) { - if (names.Length()>0) names+=", "; - const char* colname = col->GetName(); - if (forcequote || (strpbrk(colname,"[:.]<>")!=0)) { - names+=quote; - names+=colname; - names+=quote; - } else names+=colname; - - if (values.Length()>0) values+=", "; + if (first) first = kFALSE; + else values+=", "; if (col->IsNumeric()) values+=col->GetValue(); else { TString value = col->GetValue(); - AddBrackets(value, valuequote); + TSQLStructure::AddStrBrackets(value, valuequote); values += value; } } + + TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo); + if (buf!=0) buf->AddValues(kTRUE, values.Data()); - TString cmd; - cmd.Form("INSERT INTO %s%s%s (%s) VALUES(%s)", - quote, tablename, quote, - names.Data(), values.Data()); - AddSqlCmd(cmd.Data()); } }; //________________________________________________________________________ -Int_t TSQLStructure::FindMaxRef() +Long64_t TSQLStructure::FindMaxObjectId() { // define maximum reference id, used for objects - Int_t max = 0; - if ((GetType()==kSqlPointer) || (GetType()==kSqlObject)) - max = atoi(fValue.Data()); + Long64_t max = DefineObjectId(kFALSE); for (Int_t n=0;n<NumChilds();n++) { - Int_t zn = GetChild(n)->FindMaxRef(); + Long64_t zn = GetChild(n)->FindMaxObjectId(); if (zn>max) max = zn; } @@ -825,7 +916,7 @@ Int_t TSQLStructure::FindMaxRef() } //________________________________________________________________________ -Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Int_t keyid, TObjArray* cmds) +Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Long64_t keyid, TObjArray* cmds) { // Convert structure to sql statements // This function is called immidiately after TBufferSQL2 produces @@ -839,13 +930,15 @@ Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Int_t keyid, TObjArray* cm reg.fCmds = cmds; reg.f = file; reg.fKeyId = keyid; - reg.fFirstObjId = atoi(GetValue()); // this is id of main object to be stored + // this is id of main object to be stored + reg.fFirstObjId = DefineObjectId(kFALSE); // this is maximum objectid which is now in use - reg.fLastObjId = FindMaxRef(); + reg.fLastObjId = FindMaxObjectId(); - Bool_t res = StoreObject(®, GetValue(), GetObjectClass()); + Bool_t res = StoreObject(®, reg.fFirstObjId, GetObjectClass()); - cmds->AddAll(&(reg.fRegCmds)); + // convert values from pool to SQL commands + reg.ConvertPoolValues(); return res; } @@ -863,7 +956,7 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const switch (fType) { case kSqlObject: { - if (!StoreObject(reg, GetValue(), GetObjectClass())) break; + if (!StoreObject(reg, DefineObjectId(kFALSE), GetObjectClass())) break; AddCmd(blobs, sqlio::ObjectRef, GetValue(), topname, ns); @@ -895,15 +988,16 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const child->PerformConversion(reg, blobs, info->GetName(), useblob); } } else { - Int_t objid = reg->GetNextObjId(); + Long64_t objid = reg->GetNextObjId(); TString sobjid; - sobjid.Form("%d",objid); - if (!StoreObject(reg, sobjid.Data(), info->GetClass(), kTRUE)) return; + sobjid.Form("%lld",objid); + if (!StoreObject(reg, objid, info->GetClass(), kTRUE)) return; AddCmd(blobs, sqlio::ObjectInst, sobjid.Data(), topname, ns); } break; } + case kSqlCustomElement: case kSqlElement: { const TStreamerElement* elem = (const TStreamerElement*) fPointer; @@ -934,7 +1028,7 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const Int_t size = strlen(value); if (size > reg->f->SQLSmallTextTypeLimit()) { Int_t strid = reg->AddLongString(value); - buf = reg->f->CodeLongString(atoi(reg->fCurrentObjId.Data()), strid); + buf = reg->f->CodeLongString(reg->fCurrentObjId, strid); value = buf.Data(); } } @@ -957,13 +1051,13 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const } //________________________________________________________________________ -Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, const char* objid, TClass* cl, Bool_t registerobj) +Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl, Bool_t registerobj) { // convert object data to sql statements // if normal (columnwise) representation is not possible, // complete object will be converted to raw format - if (cl==0) return kFALSE; + if ((cl==0) || (objid<0)) return kFALSE; if (gDebug>1) { cout << "Store object " << objid <<" cl = " << cl->GetName() << endl; @@ -973,7 +1067,7 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, const char* objid, TClass* TSQLClassInfo* sqlinfo = 0; - TString oldid = reg->fCurrentObjId; + Long64_t oldid = reg->fCurrentObjId; TClass* oldcl = reg->fCurrentObjClass; reg->fCurrentObjId = objid; @@ -983,22 +1077,19 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, const char* objid, TClass* Bool_t res = kTRUE; - Bool_t isclonesarray = kFALSE; //(cl==TClonesArray::Class()); - if (cl==TObject::Class()) normstore = StoreTObject(reg); else if (cl==TString::Class()) normstore = StoreTString(reg); else - if (!isclonesarray) - if (GetType()==kSqlStreamerInfo) - // this is a case when array of objects are stored in blob and each object - // has normal streamer. Then it will be stored in normal form and only one tag - // will be kept to remind about - normstore = StoreClassInNormalForm(reg); - else - normstore = StoreObjectInNormalForm(reg); + if (GetType()==kSqlStreamerInfo) + // this is a case when array of objects are stored in blob and each object + // has normal streamer. Then it will be stored in normal form and only one tag + // will be kept to remind about + normstore = StoreClassInNormalForm(reg); + else + normstore = StoreObjectInNormalForm(reg); if (gDebug>2) cout << "Store object " << objid << " of class " << cl->GetName() << " normal = " << normstore << " sqltype = " << GetType() << endl; @@ -1010,7 +1101,7 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, const char* objid, TClass* // when TClonesArray, all data will be stored in raw format for(Int_t n=0;n<NumChilds();n++) { TSQLStructure* child = GetChild(n); - child->PerformConversion(reg, &objblobs, 0 /*cl->GetName()*/, isclonesarray); + child->PerformConversion(reg, &objblobs, 0 /*cl->GetName()*/); } if (objblobs.GetLast()<0) @@ -1025,11 +1116,8 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, const char* objid, TClass* objblobs.Delete(); } - if (registerobj) { - Int_t objidint = atoi(objid); - TString regcmd = reg->f->SetObjectDataCmd(reg->fKeyId, objidint, cl); - reg->AddRegCmd(regcmd.Data(), objidint); - } + if (registerobj) + reg->AddRegCmd(objid, cl); reg->fCurrentObjId = oldid; reg->fCurrentObjClass = oldcl; @@ -1048,7 +1136,7 @@ Bool_t TSQLStructure::StoreObjectInNormalForm(TSqlRegistry* reg) TSQLStructure* s_ver = GetChild(0); TSQLStructure* s_info = GetChild(1); - + if (!CheckNormalClassPair(s_ver, s_info)) return kFALSE; return s_info->StoreClassInNormalForm(reg); @@ -1060,10 +1148,10 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg) // produces data for complete class table // where not possible, raw data for some elements are created - TStreamerInfo* info = GetStreamerInfo(); - if (info==0) return kFALSE; - TClass* cl = info->GetClass(); - Int_t version = info->GetClassVersion(); + TClass* cl = 0; + Version_t version = 0; + if (!GetClassInfo(cl, version)) return kFALSE; + if (cl==0) return kFALSE; TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl->GetName(), version); @@ -1073,7 +1161,7 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg) Int_t currrawid = 0; // add first column with object id - columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->f->SQLIntType(), reg->fCurrentObjId, kTRUE)); + columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId)); for(Int_t n=0;n<=fChilds.GetLast();n++) { TSQLStructure* child = (TSQLStructure*) fChilds.At(n); @@ -1102,7 +1190,7 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg) if (doblobs) child->PerformConversion(reg, &blobs, elem->GetName(), kFALSE); - + Int_t blobid = -1; if (blobs.GetLast()>=0) { blobid = currrawid; // column will contain first raw id @@ -1120,7 +1208,7 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg) reg->f->SyncSQLClassInfo(sqlinfo, &columns, needblob); - reg->InsertToNormalTable(&columns, sqlinfo->GetClassTableName()); + reg->InsertToNormalTable(&columns, sqlinfo); columns.Delete(); @@ -1178,7 +1266,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col columns->Add(new TSQLColumnData(colname.Data(), stype, value, kFALSE)); else { Int_t strid = reg->AddLongString(value); - TString buf = reg->f->CodeLongString(atoi(reg->fCurrentObjId.Data()), strid); + TString buf = reg->f->CodeLongString(reg->fCurrentObjId, strid); columns->Add(new TSQLColumnData(colname.Data(), stype, buf.Data(), kFALSE)); } @@ -1186,10 +1274,10 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col } if (columntyp==kColParent) { - TString objid = reg->fCurrentObjId; // DefineObjectIdStr(); + Long64_t objid = reg->fCurrentObjId; TClass* basecl = elem->GetClassPointer(); Int_t resversion = basecl->GetClassVersion(); - if (!StoreObject(reg, objid.Data(), basecl, kFALSE)) + if (!StoreObject(reg, objid, basecl, kFALSE)) resversion = -1; columns->Add(new TSQLColumnData(colname.Data(), resversion)); return kTRUE; @@ -1197,27 +1285,26 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col if (columntyp==kColObject) { - TString sobjid; - Int_t objid = 0; + Long64_t objid = -1; if (NumChilds()==1) { TSQLStructure* child = GetChild(0); if (child->GetType()==kSqlObject) { - if (!child->StoreObject(reg, child->GetValue(), child->GetObjectClass())) return kFALSE; - sobjid = child->GetValue(); + objid = child->DefineObjectId(kFALSE); + if (!child->StoreObject(reg, objid, child->GetObjectClass())) return kFALSE; } else - if (child->GetType()==kSqlPointer) - sobjid = child->GetValue(); + if (child->GetType()==kSqlPointer) { + TString sobjid = child->GetValue(); + if (sobjid.Length()>0) + objid = sqlio::atol64(sobjid.Data()); + } } - if (sobjid.Length()>0) { - objid = sobjid.Atoi(); - } else { + if (objid<0) { //cout << "!!!! Not standard " << elem->GetName() << " class = " << elem->GetClassPointer()->GetName() << endl; objid = reg->GetNextObjId(); - sobjid.Form("%d",objid); - if (!StoreObject(reg, sobjid.Data(), elem->GetClassPointer())) + if (!StoreObject(reg, objid, elem->GetClassPointer())) objid = -1; // this is a case, when no data was stored for this object } @@ -1236,16 +1323,20 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE; Bool_t normal = kTRUE; + + Long64_t objid = -1; - if (child->GetType()==kSqlObject) - normal = child->StoreObject(reg, child->GetValue(), child->GetObjectClass()); + if (child->GetType()==kSqlObject) { + objid = child->DefineObjectId(kFALSE); + normal = child->StoreObject(reg, objid, child->GetObjectClass()); + } if (!normal) { Error("kColNormObject","child->StoreObject fails"); return kFALSE; } - columns->Add(new TSQLColumnData(colname.Data(), "INT", child->GetValue(), kTRUE)); + columns->Add(new TSQLColumnData(colname.Data(), objid)); return kTRUE; } @@ -1258,14 +1349,18 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col (child->GetType()!=kSqlObject)) return kFALSE; Bool_t normal = kTRUE; - if (child->GetType()==kSqlObject) - normal = child->StoreObject(reg, child->GetValue(), child->GetObjectClass()); + Long64_t objid = -1; + + if (child->GetType()==kSqlObject) { + objid = child->DefineObjectId(kFALSE); + normal = child->StoreObject(reg, objid, child->GetObjectClass()); + } if (!normal) return kFALSE; colname = DefineElementColumnName(elem, reg->f, index); - columns->Add(new TSQLColumnData(colname.Data(), "INT", child->GetValue(), kTRUE)); + columns->Add(new TSQLColumnData(colname.Data(), objid)); } return kTRUE; } @@ -1276,13 +1371,16 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col if ((child->GetType()!=kSqlPointer) && (child->GetType()!=kSqlObject)) return kFALSE; Bool_t normal = kTRUE; + Long64_t objid = -1; - if (child->GetType()==kSqlObject) - normal = child->StoreObject(reg, child->GetValue(), child->GetObjectClass()); + if (child->GetType()==kSqlObject) { + objid = child->DefineObjectId(kFALSE); + normal = child->StoreObject(reg, objid, child->GetObjectClass()); + } if (!normal) return kFALSE; - columns->Add(new TSQLColumnData(colname.Data(), "INT", child->GetValue(), kTRUE)); + columns->Add(new TSQLColumnData(colname.Data(), objid)); return kTRUE; } @@ -1367,14 +1465,15 @@ Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TObjArray* blobs) while (indx<NumChilds()-1) { indx++; //TSQLStructure* s_ver = GetChild(indx++); TSQLStructure* s_info = GetChild(indx++); - TStreamerInfo* info = s_info->GetStreamerInfo(); - Int_t objid = reg->GetNextObjId(); - TString sobjid; - sobjid.Form("%d",objid); - if (!s_info->StoreObject(reg, sobjid.Data(), info->GetClass())) { + TClass* cl = 0; + Version_t version = 0; + if (!s_info->GetClassInfo(cl, version)) return kFALSE; + Long64_t objid = reg->GetNextObjId(); + if (!s_info->StoreObject(reg, objid, cl)) objid = -1; // this is a case, when no data was stored for this object - sobjid = "-1"; - } + + TString sobjid; + sobjid.Form("%lld", objid); AddCmd(blobs, sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns); } @@ -1388,12 +1487,16 @@ Bool_t TSQLStructure::CheckNormalClassPair(TSQLStructure* s_ver, TSQLStructure* // check if pair of two element corresponds // to start of object, stored in normal form - if ((s_ver==0) || (s_info==0) || (s_ver->GetType()!=kSqlVersion) || - (s_info->GetType()!=kSqlStreamerInfo)) return kFALSE; + if ((s_ver==0) || (s_info==0) || (s_ver->GetType()!=kSqlVersion)) return kFALSE; + + TClass* ver_cl = s_ver->GetVersionClass(); - TClass* cl = s_ver->GetVersionClass(); - TStreamerInfo* info = s_info->GetStreamerInfo(); - if ((cl==0) || (cl!=info->GetClass()) || (cl->GetClassVersion()!=info->GetClassVersion())) return kFALSE; + TClass* info_cl = 0; + Version_t info_ver = 0; + if (!s_info->GetClassInfo(info_cl, info_ver)) return kFALSE; + + if ((ver_cl==0) || (info_cl==0) || (ver_cl!=info_cl) || + (ver_cl->GetClassVersion()!=info_ver)) return kFALSE; return kTRUE; } @@ -1429,7 +1532,7 @@ Bool_t TSQLStructure::StoreTObject(TSqlRegistry* reg) const char* uinttype = reg->f->SQLCompatibleType(TStreamerInfo::kUInt); - columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->f->SQLIntType(), reg->fCurrentObjId, kTRUE)); + columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId)); columns.Add(new TSQLColumnData(sqlio::TObjectUniqueId, uinttype, str_id->GetValue(), kTRUE)); columns.Add(new TSQLColumnData(sqlio::TObjectBits, uinttype, str_bits->GetValue(), kTRUE)); @@ -1437,7 +1540,7 @@ Bool_t TSQLStructure::StoreTObject(TSqlRegistry* reg) reg->f->SyncSQLClassInfo(sqlinfo, &columns, kFALSE); - reg->InsertToNormalTable(&columns, sqlinfo->GetClassTableName()); + reg->InsertToNormalTable(&columns, sqlinfo); columns.Delete(); @@ -1458,11 +1561,11 @@ Bool_t TSQLStructure::StoreTString(TSqlRegistry* reg) TObjArray columns; - columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->f->SQLIntType(), reg->fCurrentObjId, kTRUE)); + columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId)); columns.Add(new TSQLColumnData(sqlio::TStringValue, reg->f->SQLBigTextType(), value, kFALSE)); reg->f->SyncSQLClassInfo(sqlinfo, &columns, kFALSE); - reg->InsertToNormalTable(&columns, sqlinfo->GetClassTableName()); + reg->InsertToNormalTable(&columns, sqlinfo); columns.Delete(); return kTRUE; } @@ -1516,6 +1619,8 @@ Int_t TSQLStructure::DefineElementColumnType(TStreamerElement* elem, TSQLFile* f if (elem==0) return kColUnknown; Int_t typ = elem->GetType(); + + if (typ == TStreamerInfo::kMissing) return kColRawData; if ((typ>0) && (typ<20) && (typ!=TStreamerInfo::kCharStar)) return kColSimple; @@ -1572,7 +1677,6 @@ Int_t TSQLStructure::DefineElementColumnType(TStreamerElement* elem, TSQLFile* f if (elem->GetStreamer()!=0) return kColNormObject; else return kColNormObjectArray; - if ((typ==TStreamerInfo::kObject) || (typ==TStreamerInfo::kAny) || (typ==TStreamerInfo::kAnyp) || @@ -1685,13 +1789,10 @@ TString TSQLStructure::DefineElementColumnName(TStreamerElement* elem, TSQLFile* } //________________________________________________________________________ -Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) +Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data) { // find column in TSQLObjectData object, which correspond to current element - // for TClonesArray do nothing, just exit - if (IsClonesArray()) return kColClonesArray; - TStreamerElement* elem = GetElement(); if ((elem==0) || (data==0)) return kColUnknown; @@ -1708,6 +1809,10 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) TString colname = DefineElementColumnName(elem, f); + if (gDebug>4) + cout << " colname = " << colname << " in " << + data->GetInfo()->GetClassTableName() << endl; + switch (coltype) { case kColSimple: { located = data->LocateColumn(colname.Data()); @@ -1723,16 +1828,16 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) located = data->LocateColumn(colname.Data()); if (located==kColUnknown) return kColUnknown; - Int_t objid = DefineObjectId(); + Long64_t objid = DefineObjectId(kTRUE); const char* clname = elemname; - Int_t version = atoi(data->GetValue()); + Version_t version = atoi(data->GetValue()); // this is a case, when parent store nothing in the database if (version<0) break; // special treatment for TObject if (strcmp(clname,TObject::Class()->GetName())==0) { - UnpackTObject(f, data, objid, version); + UnpackTObject(f, buf, data, objid, version); break; } @@ -1743,7 +1848,7 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) if (sqlinfo->IsClassTableExist()) { data->AddUnpackInt(sqlio::Version, version); } else { - TSQLObjectData* objdata = f->GetObjectClassData(objid, sqlinfo); + TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo); if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown; AddObjectData(objdata); } @@ -1765,7 +1870,7 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) const char* strobjid = data->GetValue(); if (strobjid==0) return kColUnknown; - Int_t objid = atoi(strobjid); + Long64_t objid = sqlio::atol64(strobjid); // when nothing was stored, nothing need to be read. skip if (objid<0) break; @@ -1773,11 +1878,11 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) TString clname; Version_t version; - if (!f->GetObjectData(objid, clname, version)) return kColUnknown; + if (!buf->SqlObjectInfo(objid, clname, version)) return kColUnknown; // special treatment for TObject if (clname==TObject::Class()->GetName()) { - UnpackTObject(f, data, objid, version); + UnpackTObject(f, buf, data, objid, version); break; } @@ -1787,7 +1892,7 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) if (sqlinfo->IsClassTableExist()) { data->AddUnpackInt(sqlio::Version, version); } else { - TSQLObjectData* objdata = f->GetObjectClassData(objid, sqlinfo); + TSQLObjectData* objdata = buf->SqlObjectData(objid, sqlinfo); if ((objdata==0) || !objdata->PrepareForRawData()) return kColUnknown; AddObjectData(objdata); } @@ -1826,8 +1931,8 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) if (located==kColUnknown) return located; const char* value = data->GetValue(); - Int_t objid = DefineObjectId(); - Int_t strid = f->IsLongStringCode(value, objid); + Long64_t objid = DefineObjectId(kTRUE); + Int_t strid = f->IsLongStringCode(objid, value); TString buf; @@ -1865,14 +1970,14 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TSQLObjectData* data) } //________________________________________________________________________ -Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TSQLObjectData* data, Int_t objid, Int_t clversion) +Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion) { // Unpack TObject data in form, understodable by custom TObject streamer TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(TObject::Class()->GetName(), clversion); if (sqlinfo==0) return kFALSE; - TSQLObjectData* tobjdata = f->GetObjectClassData(objid, sqlinfo); + TSQLObjectData* tobjdata = buf->SqlObjectData(objid, sqlinfo); if (tobjdata==0) return kFALSE; data->AddUnpackInt(sqlio::Version, clversion); @@ -1896,14 +2001,14 @@ Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TSQLObjectData* data, Int_t obj } //________________________________________________________________________ -Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TSQLObjectData* data, Int_t objid, Int_t clversion) +Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TBufferSQL2* buf, TSQLObjectData* data, Long64_t objid, Int_t clversion) { // Unpack TString data in form, understodable by custom TString streamer TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(TString::Class()->GetName(), clversion); if (sqlinfo==0) return kFALSE; - TSQLObjectData* tstringdata = f->GetObjectClassData(objid, sqlinfo); + TSQLObjectData* tstringdata = buf->SqlObjectData(objid, sqlinfo); if (tstringdata==0) return kFALSE; tstringdata->LocateColumn(sqlio::TStringValue); @@ -1924,3 +2029,13 @@ Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TSQLObjectData* data, Int_t obj return kTRUE; } + +//________________________________________________________________________ +void TSQLStructure::AddStrBrackets(TString &s, const char* quote) +{ + // adds quotes arround string value and replaces some special symbols + if (strcmp(quote,"\"")==0) s.ReplaceAll("\"","\\\""); + else s.ReplaceAll("'","''"); + s.Prepend(quote); + s.Append(quote); +} diff --git a/xml/inc/TKeyXML.h b/xml/inc/TKeyXML.h index 2c38455bdb9..4743f4373c2 100644 --- a/xml/inc/TKeyXML.h +++ b/xml/inc/TKeyXML.h @@ -1,4 +1,4 @@ -// @(#)root/xml:$Name: $:$Id: TKeyXML.h,v 1.3 2005/11/20 05:07:41 pcanal Exp $ +// @(#)root/xml:$Name: $:$Id: TKeyXML.h,v 1.4 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev 10.05.2004 /************************************************************************* @@ -26,19 +26,18 @@ class TKeyXML : public TKey { TKeyXML(); public: - TKeyXML(TXMLFile* file, const TObject* obj, const char* name = 0); - TKeyXML(TXMLFile* file, const void* obj, const TClass* cl, const char* name); - TKeyXML(TXMLFile* file, XMLNodePointer_t keynode); + TKeyXML(TDirectory* mother, const TObject* obj, const char* name = 0); + TKeyXML(TDirectory* mother, const void* obj, const TClass* cl, const char* name); + TKeyXML(TDirectory* mother, XMLNodePointer_t keynode); virtual ~TKeyXML(); // redefined TKey Methods - virtual void Browse(TBrowser *b); virtual void Delete(Option_t *option=""); virtual void DeleteBuffer() {} virtual void FillBuffer(char *&) {} virtual char *GetBuffer() const { return 0; } - virtual Long64_t GetSeekKey() const { return 1; } - virtual Long64_t GetSeekPdir() const { return 1;} + virtual Long64_t GetSeekKey() const { return fKeyNode ? 1024 : 0;} + virtual Long64_t GetSeekPdir() const { return fKeyNode ? 1024 : 0;} //virtual ULong_t Hash() const { return 0; } virtual void Keep() {} //virtual void ls(Option_t* ="") const; @@ -51,26 +50,19 @@ class TKeyXML : public TKey { virtual void ReadBuffer(char *&) {} virtual void ReadFile() {} virtual void SetBuffer() { fBuffer = 0; } - virtual void SetParent(const TObject* ) { } - virtual Int_t Sizeof() const { return 0; } virtual Int_t WriteFile(Int_t =1, TFile* = 0) { return 0; } // TKeyXML specific methods XMLNodePointer_t KeyNode() const { return fKeyNode; } - void SetXML(TXMLEngine* xml) { fXML = xml; } - protected: virtual Int_t Read(const char *name) { return TKey::Read(name); } void StoreObject(const void* obj, const TClass* cl); - XMLNodePointer_t ObjNode(); - XMLNodePointer_t BlockNode(); + TXMLEngine* XMLEngine(); void* XmlReadAny(void* obj, const TClass* expectedClass); - TXMLFile* fFile; //! - TXMLEngine* fXML; //! XMLNodePointer_t fKeyNode; //! ClassDef(TKeyXML,1) // a special TKey for XML files diff --git a/xml/inc/TXMLFile.h b/xml/inc/TXMLFile.h index e6b692a67aa..a1582abfec3 100644 --- a/xml/inc/TXMLFile.h +++ b/xml/inc/TXMLFile.h @@ -1,4 +1,4 @@ -// @(#)root/xml:$Name: $:$Id: TXMLFile.h,v 1.11 2005/11/28 23:22:31 pcanal Exp $ +// @(#)root/xml:$Name: $:$Id: TXMLFile.h,v 1.12 2006/01/20 01:12:13 pcanal Exp $ // Author: Sergey Linev 10.05.2004 /************************************************************************* @@ -52,6 +52,8 @@ class TXMLFile : public TFile, public TXMLSetup { virtual ~TXMLFile(); virtual void Close(Option_t *option=""); // *MENU* + virtual TKey* CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize); + virtual TKey* CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize); virtual void DrawMap(const char* ="*",Option_t* ="") {} virtual void FillBuffer(char* &) {} virtual void Flush() {} @@ -105,9 +107,6 @@ class TXMLFile : public TFile, public TXMLSetup { protected: // functions to store streamer infos - virtual TKey* CreateKey(const TObject* obj, const char* name, Int_t bufsize); - virtual TKey* CreateKey(const void* obj, const TClass* cl, const char* name, Int_t bufsize); - void StoreStreamerElement(XMLNodePointer_t node, TStreamerElement* elem); void ReadStreamerElement(XMLNodePointer_t node, TStreamerInfo* info); diff --git a/xml/src/TBufferXML.cxx b/xml/src/TBufferXML.cxx index c6b70f65d48..1e5c722cfe7 100644 --- a/xml/src/TBufferXML.cxx +++ b/xml/src/TBufferXML.cxx @@ -1,4 +1,4 @@ -// @(#)root/:$Name: $:$Id: TBufferXML.cxx,v 1.8 2006/01/20 01:12:13 pcanal Exp $ +// @(#)root/:$Name: $:$Id: TBufferXML.cxx,v 1.9 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev, Rene Brun 10.05.2004 /************************************************************************* @@ -89,6 +89,7 @@ TBufferXML::TBufferXML(TBuffer::EMode mode) : SetParent(0); SetBit(kCannotHandleMemberWiseStreaming); + SetBit(kTextBasedStreaming); } //______________________________________________________________________________ @@ -117,6 +118,7 @@ TBufferXML::TBufferXML(TBuffer::EMode mode, TXMLFile* file) : SetParent(file); SetBit(kCannotHandleMemberWiseStreaming); + SetBit(kTextBasedStreaming); if (XmlFile()) { SetXML(XmlFile()->XML()); SetCompressionLevel(XmlFile()->GetCompressionLevel()); @@ -1031,6 +1033,9 @@ void TBufferXML::ClassMember(const char* name, const char* typeName, Int_t arrsi Int_t typ_id = -1; + if (strcmp(typeName,"raw:data")==0) + typ_id = TStreamerInfo::kMissing; + if (typ_id<0) { TDataType *dt = gROOT->GetType(typeName); if (dt!=0) @@ -1068,6 +1073,11 @@ void TBufferXML::ClassMember(const char* name, const char* typeName, Int_t arrsi TStreamerElement* elem = 0; + if (typ_id == TStreamerInfo::kMissing) { + elem = new TStreamerElement(name,"title",0, typ_id, "raw:data"); + } else + + if (typ_id==TStreamerInfo::kBase) { TClass* cl = gROOT->GetClass(tname.Data()); if (cl!=0) { diff --git a/xml/src/TKeyXML.cxx b/xml/src/TKeyXML.cxx index b4e4d94fcc9..0cd49c9350b 100644 --- a/xml/src/TKeyXML.cxx +++ b/xml/src/TKeyXML.cxx @@ -1,4 +1,4 @@ -// @(#)root/xml:$Name: $:$Id: TKeyXML.cxx,v 1.5 2006/01/20 01:12:13 pcanal Exp $ +// @(#)root/xml:$Name: $:$Id: TKeyXML.cxx,v 1.6 2006/01/25 16:00:11 pcanal Exp $ // Author: Sergey Linev, Rene Brun 10.05.2004 /************************************************************************* @@ -30,18 +30,14 @@ ClassImp(TKeyXML); //______________________________________________________________________________ TKeyXML::TKeyXML() : TKey(), - fFile(0), - fXML(0), fKeyNode(0) { // default constructor } //______________________________________________________________________________ -TKeyXML::TKeyXML(TXMLFile* file, const TObject* obj, const char* name) : - TKey(), - fFile(file), - fXML(file->XML()), +TKeyXML::TKeyXML(TDirectory* mother, const TObject* obj, const char* name) : + TKey(mother), fKeyNode(0) { // Creates TKeyXML and convert obj data to xml structures @@ -59,10 +55,8 @@ TKeyXML::TKeyXML(TXMLFile* file, const TObject* obj, const char* name) : } //______________________________________________________________________________ -TKeyXML::TKeyXML(TXMLFile* file, const void* obj, const TClass* cl, const char* name) : - TKey(), - fFile(file), - fXML(file->XML()), +TKeyXML::TKeyXML(TDirectory* mother, const void* obj, const TClass* cl, const char* name) : + TKey(mother), fKeyNode(0) { // Creates TKeyXML and convert obj data to xml structures @@ -74,60 +68,39 @@ TKeyXML::TKeyXML(TXMLFile* file, const void* obj, const TClass* cl, const char* } //______________________________________________________________________________ -TKeyXML::TKeyXML(TXMLFile* file, XMLNodePointer_t keynode) : - TKey(), - fFile(file), - fXML(file->XML()), +TKeyXML::TKeyXML(TDirectory* mother, XMLNodePointer_t keynode) : + TKey(mother), fKeyNode(keynode) { // Creates TKeyXML and takes ownership over xml node, from which object can be restored - SetName(fXML->GetAttr(keynode, xmlio::Name)); + TXMLEngine* xml = XMLEngine(); + + SetName(xml->GetAttr(keynode, xmlio::Name)); - if (fXML->HasAttr(keynode, xmlio::Title)) - SetTitle(fXML->GetAttr(keynode, xmlio::Title)); + if (xml->HasAttr(keynode, xmlio::Title)) + SetTitle(xml->GetAttr(keynode, xmlio::Title)); - fCycle = fXML->GetIntAttr(keynode, xmlio::Cycle); + fCycle = xml->GetIntAttr(keynode, xmlio::Cycle); - if (fXML->HasAttr(keynode, xmlio::CreateTm)) { - TDatime tm(fXML->GetAttr(keynode, xmlio::CreateTm)); + if (xml->HasAttr(keynode, xmlio::CreateTm)) { + TDatime tm(xml->GetAttr(keynode, xmlio::CreateTm)); fDatime = tm; } - XMLNodePointer_t objnode = fXML->GetChild(keynode); - fXML->SkipEmpty(objnode); + XMLNodePointer_t objnode = xml->GetChild(keynode); + xml->SkipEmpty(objnode); - fClassName = fXML->GetAttr(objnode, xmlio::ObjClass); + fClassName = xml->GetAttr(objnode, xmlio::ObjClass); } //______________________________________________________________________________ TKeyXML::~TKeyXML() { // TKeyXML destructor - if (fKeyNode) - fXML->FreeNode(fKeyNode); -} - -//______________________________________________________________________________ -void TKeyXML::Browse(TBrowser *b) -{ - // Browse object corresponding to this key - - TObject *obj = gDirectory->GetList()->FindObject(GetName()); - if (obj && !obj->IsFolder()) { - if (obj->InheritsFrom(TCollection::Class())) - obj->Delete(); // delete also collection elements - delete obj; - obj = 0; - } - - if (!obj) - obj = ReadObj(); - - if (b && obj) { - obj->Browse(b); - b->SetRefreshFlag(kTRUE); - } + TXMLEngine* xml = XMLEngine(); + if (fKeyNode && xml) + xml->FreeNode(fKeyNode); } //______________________________________________________________________________ @@ -136,67 +109,52 @@ void TKeyXML::Delete(Option_t * /*option*/) // Delete key from current directory // Note: TKeyXML object is not deleted. You still have to call "delete key" - gDirectory->GetListOfKeys()->Remove(this); + TXMLEngine* xml = XMLEngine(); + if (fKeyNode && xml) { + xml->FreeNode(fKeyNode); + fKeyNode = 0; + } + + fMotherDir->GetListOfKeys()->Remove(this); } //______________________________________________________________________________ void TKeyXML::StoreObject(const void* obj, const TClass* cl) { // convert object to xml structure and keep this structure in key + + TXMLFile* f = (TXMLFile*) GetFile(); + TXMLEngine* xml = XMLEngine(); + if ((f==0) || (xml==0)) return; - fCycle = fFile->AppendKey(this); + fCycle = GetMotherDir()->AppendKey(this); - fKeyNode = fXML->NewChild(0, 0, xmlio::Xmlkey, 0); - fXML->NewAttr(fKeyNode, 0, xmlio::Name, GetName()); + fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0); + xml->NewAttr(fKeyNode, 0, xmlio::Name, GetName()); - fXML->NewIntAttr(fKeyNode, xmlio::Cycle, fCycle); + xml->NewIntAttr(fKeyNode, xmlio::Cycle, fCycle); - if (fFile->GetIOVersion()>1) { + if (f->GetIOVersion()>1) { if (strlen(GetTitle())>0) - fXML->NewAttr(fKeyNode, 0, xmlio::Title, GetTitle()); + xml->NewAttr(fKeyNode, 0, xmlio::Title, GetTitle()); fDatime.Set(); - fXML->NewAttr(fKeyNode, 0, xmlio::CreateTm, fDatime.AsSQLString()); + xml->NewAttr(fKeyNode, 0, xmlio::CreateTm, fDatime.AsSQLString()); } - TBufferXML buffer(TBuffer::kWrite, fFile); - if (fFile->GetIOVersion()==1) + TBufferXML buffer(TBuffer::kWrite, f); + if (f->GetIOVersion()==1) buffer.SetBit(TBuffer::kCannotHandleMemberWiseStreaming, kFALSE); XMLNodePointer_t node = buffer.XmlWriteAny(obj, cl); if (node!=0) - fXML->AddChild(fKeyNode, node); + xml->AddChild(fKeyNode, node); buffer.XmlWriteBlock(fKeyNode); if (cl) fClassName = cl->GetName(); } -//______________________________________________________________________________ -XMLNodePointer_t TKeyXML::ObjNode() -{ - // return starting node, where object was stored - - if (fKeyNode==0) return 0; - XMLNodePointer_t node = fXML->GetChild(fKeyNode); - fXML->SkipEmpty(node); - return node; -} - -//______________________________________________________________________________ -XMLNodePointer_t TKeyXML::BlockNode() -{ - // return node, where key binary data is stored - if (fKeyNode==0) return 0; - XMLNodePointer_t node = fXML->GetChild(fKeyNode); - fXML->SkipEmpty(node); - while (node!=0) { - if (strcmp(fXML->GetNodeName(node), xmlio::XmlBlock)==0) return node; - fXML->ShiftToNext(node); - } - return 0; -} - //______________________________________________________________________________ Int_t TKeyXML::Read(TObject* tobj) { @@ -220,7 +178,17 @@ TObject* TKeyXML::ReadObj() TObject* tobj = (TObject*) XmlReadAny(0, TObject::Class()); - if ((tobj!=0) && gROOT->GetForceStyle()) tobj->UseCurrentStyle(); + if (tobj!=0) { + if (gROOT->GetForceStyle()) tobj->UseCurrentStyle(); + if (tobj->IsA() == TDirectory::Class()) { + TDirectory *dir = (TDirectory*) tobj; + dir->SetName(GetName()); + dir->SetTitle(GetTitle()); + dir->ReadKeys(); + dir->SetMother(fMotherDir); + fMotherDir->Append(dir); + } + } return tobj; } @@ -238,17 +206,31 @@ void* TKeyXML::XmlReadAny(void* obj, const TClass* expectedClass) { // read object from key and cast to expected class - if (fKeyNode==0) return 0; + if (fKeyNode==0) return obj; + + TXMLFile* f = (TXMLFile*) GetFile(); + TXMLEngine* xml = XMLEngine(); + if ((f==0) || (xml==0)) return obj; - TBufferXML buffer(TBuffer::kRead, fFile); - if (fFile->GetIOVersion()==1) + TBufferXML buffer(TBuffer::kRead, f); + if (f->GetIOVersion()==1) buffer.SetBit(TBuffer::kCannotHandleMemberWiseStreaming, kFALSE); - buffer.XmlReadBlock(BlockNode()); + + XMLNodePointer_t blocknode = xml->GetChild(fKeyNode); + xml->SkipEmpty(blocknode); + while (blocknode!=0) { + if (strcmp(xml->GetNodeName(blocknode), xmlio::XmlBlock)==0) break; + xml->ShiftToNext(blocknode); + } + buffer.XmlReadBlock(blocknode); + + XMLNodePointer_t objnode = xml->GetChild(fKeyNode); + xml->SkipEmpty(objnode); TClass* cl = 0; - void* res = buffer.XmlReadAny(ObjNode(), obj, &cl); + void* res = buffer.XmlReadAny(objnode, obj, &cl); - if ((cl==0) || (res==0)) return 0; + if ((cl==0) || (res==0)) return obj; Int_t delta = 0; @@ -268,3 +250,12 @@ void* TKeyXML::XmlReadAny(void* obj, const TClass* expectedClass) return ((char*)res) + delta; } + +//______________________________________________________________________________ +TXMLEngine* TKeyXML::XMLEngine() +{ + // return pointer on TXMLEngine object, used for xml conversion + + TXMLFile* f = (TXMLFile*) GetFile(); + return f==0 ? 0 : f->XML(); +} diff --git a/xml/src/TXMLFile.cxx b/xml/src/TXMLFile.cxx index 72ca6214fff..5725899b841 100644 --- a/xml/src/TXMLFile.cxx +++ b/xml/src/TXMLFile.cxx @@ -1,4 +1,4 @@ -// @(#)root/xml:$Name: $:$Id: TXMLFile.cxx,v 1.16 2005/12/08 15:50:48 pcanal Exp $ +// @(#)root/xml:$Name: $:$Id: TXMLFile.cxx,v 1.17 2006/01/20 01:12:13 pcanal Exp $ // Author: Sergey Linev, Rene Brun 10.05.2004 /************************************************************************* @@ -140,8 +140,7 @@ TXMLFile::TXMLFile(const char* filename, Option_t* option, const char* title, In gDirectory = 0; SetName(filename); SetTitle(title); - TDirectory::Build(); - fFile = this; + TDirectory::Build(this, 0); fD = -1; fFile = this; @@ -432,19 +431,19 @@ Int_t TXMLFile::ReOpen(Option_t* mode) } //______________________________________________________________________________ -TKey* TXMLFile::CreateKey(const TObject* obj, const char* name, Int_t) +TKey* TXMLFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t) { // create XML key, which will store object in xml structures - return new TKeyXML(this, obj, name); + return new TKeyXML(mother, obj, name); } //______________________________________________________________________________ -TKey* TXMLFile::CreateKey(const void* obj, const TClass* cl, const char* name, Int_t) +TKey* TXMLFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t) { // create XML key, which will store object in xml structures - return new TKeyXML(this, obj, cl, name); + return new TKeyXML(mother, obj, cl, name); } //______________________________________________________________________________ -- GitLab