diff --git a/sql/inc/LinkDef.h b/sql/inc/LinkDef.h
index d7450200d0a07ce1c2d6171fff2f56c0279a3362..ce322ce5a2edcb1f082571c1e064a7ffd33acb86 100644
--- a/sql/inc/LinkDef.h
+++ b/sql/inc/LinkDef.h
@@ -1,4 +1,4 @@
-/* @(#)root/sql:$Name:  $:$Id: LinkDef.h,v 1.2 2005/12/07 14:59:57 rdm Exp $ */
+/* @(#)root/sql:$Name:  $:$Id: LinkDef.h,v 1.3 2006/02/01 18:57:41 pcanal Exp $ */
 
 /*************************************************************************
  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
@@ -10,14 +10,16 @@
 
 #ifdef __CINT__
 
-#pragma link C++ class TSQLFile;
+#pragma link C++ class TSQLFile-;
 #pragma link C++ class TBufferSQL2;
 #pragma link C++ class TKeySQL;
 #pragma link C++ class TSQLClassInfo;
+#pragma link C++ class TSQLClassColumnInfo;
 #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;
+#pragma link C++ class TSQLTableData;
 
 #endif
diff --git a/sql/inc/TSQLClassInfo.h b/sql/inc/TSQLClassInfo.h
index a084dba85ad09d4b72291027cb46dbeed194c7f0..f4a95e14be4de4133d5fc28e49ffb2d990b3f08d 100644
--- a/sql/inc/TSQLClassInfo.h
+++ b/sql/inc/TSQLClassInfo.h
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLClassInfo.h,v 1.3 2005/12/07 14:59:57 rdm Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLClassInfo.h,v 1.4 2006/05/22 08:55:57 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -31,15 +31,46 @@
 
 class TObjArray;
 
+class TSQLClassColumnInfo : public TObject {
+
+public:
+   TSQLClassColumnInfo();
+   TSQLClassColumnInfo(const char* name,
+                       const char* sqlname,
+                       const char* sqltype);
+   virtual ~TSQLClassColumnInfo();
+   
+   virtual const char* GetName() const { return fName.Data(); }   
+   const char* GetSQLName() const { return fSQLName.Data(); }   
+   const char* GetSQLType() const { return fSQLType.Data(); }   
+
+protected:    
+   TString   fName;
+   TString   fSQLName;
+   TString   fSQLType; 
+
+   ClassDef(TSQLClassColumnInfo, 1); //  Keeps information about single column in class table
+};
+
+//_________________________________________________________________________________
+
 class TSQLClassInfo : public TObject {
 public:
    TSQLClassInfo();
-   TSQLClassInfo(const char* classname, Int_t version);
+   TSQLClassInfo(Long64_t classid,
+                 const char* classname, 
+                 Int_t version);
    virtual ~TSQLClassInfo();
    
+
+   Long64_t GetClassId() const { return fClassId; }
+   
    virtual const char* GetName() const { return fClassName.Data(); }
    Int_t GetClassVersion() const { return fClassVersion; }
    
+   void SetClassTableName(const char* name) { fClassTable = name; }
+   void SetRawTableName(const char* name) { fRawTable = name; }
+   
    const char* GetClassTableName() const { return fClassTable.Data(); }
    const char* GetRawTableName() const { return fRawTable.Data(); }
    
@@ -51,11 +82,13 @@ public:
    Bool_t IsRawTableExist() const { return fRawtableExist; }
    
    TObjArray* GetColumns() const { return fColumns; }
+   Int_t FindColumn(const char* name, Bool_t sqlname = kFALSE);
    
 protected:
    
    TString    fClassName;            //! class name 
    Int_t      fClassVersion;         //! class version 
+   Long64_t      fClassId;              //! sql class id
    TString    fClassTable;           //! name of table with class data
    TString    fRawTable;             //! name of table with raw data
    TObjArray* fColumns;              //! name and type of columns - array of TNamed
diff --git a/sql/inc/TSQLFile.h b/sql/inc/TSQLFile.h
index 407bfae97e042a7d8a71ec3ce78684f6fc13e667..65d01704b1ef7838809c7e0e94651373d4fefd44 100644
--- a/sql/inc/TSQLFile.h
+++ b/sql/inc/TSQLFile.h
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLFile.h,v 1.7 2006/02/01 18:57:41 pcanal Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLFile.h,v 1.8 2006/05/22 08:55:57 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -41,7 +41,10 @@ class TSQLFile : public TFile {
    friend class TBufferSQL2;
    friend class TKeySQL;
    friend class TSQLStructure;
+   friend class TSQLTableData;
    friend class TSqlRegistry; 
+   friend class TSqlRawBuffer;
+   friend class TSqlCmdsBuffer;
     
 protected:
    enum ELockingKinds {
@@ -58,6 +61,12 @@ protected:
    virtual Int_t     SysStat(Int_t, Long_t*, Long64_t*, Long_t*, Long_t*) { return 0; }
    virtual Int_t     SysSync(Int_t) { return 0; }
 
+   // Overwrite methods for directory I/O
+   virtual Long64_t DirCreateEntry(TDirectory*);
+   virtual Int_t    DirReadKeys(TDirectory*);
+   virtual void     DirWriteKeys(TDirectory*);
+   virtual void     DirWriteHeader(TDirectory*);
+
    // functions to manipulate basic tables (Configurations, Objects, Keys) in database
    void              SaveToDatabase();
    Bool_t            ReadConfigurations();
@@ -68,21 +77,23 @@ protected:
    void              SetLocking(Int_t mode);
    Int_t             GetLocking();
   
-   // function for read/write access infos, not implemented
+   // function for read/write access infos
    Bool_t            IsWriteAccess();
    Bool_t            IsReadAccess();
   
    // generic sql functions
    TSQLResult*       SQLQuery(const char* cmd, Int_t flag = 0, Bool_t* res = 0);
+   Bool_t            SQLCanStatement();
+   TSQLStatement*    SQLStatement(const char* cmd, Int_t bufsize = 1000);
+   void              SQLDeleteStatement(TSQLStatement* stmt);
    Bool_t            SQLApplyCommands(TObjArray* cmds);
-   TObjArray*        SQLTablesList(const char* searchtable = 0);
    Bool_t            SQLTestTable(const char* tablename);
-   TObjArray*        SQLTableColumns(const char* tablename);
    Long64_t          SQLMaximumValue(const char* tablename, const char* columnname);
    void              SQLDeleteAllTables();
    Bool_t            SQLStartTransaction();
    Bool_t            SQLCommit();
    Bool_t            SQLRollback();
+   Int_t             SQLMaxIdentifierLength();
 
    // operation with keys structures in database
    void              DeleteKeyFromDB(Long64_t keyid);
@@ -94,11 +105,18 @@ protected:
 
    // handling SQL class info structures
    TSQLClassInfo*    FindSQLClassInfo(const char* clname, Int_t version);
-   TSQLClassInfo*    RequestSQLClassInfo(const char* clname, Int_t version, Bool_t force = kFALSE);
-   TSQLClassInfo*    RequestSQLClassInfo(const TClass* cl, Bool_t force = kFALSE);
-   Bool_t            SyncSQLClassInfoRawTables(TSQLClassInfo* sqlinfo, Bool_t hasrawdata);
-   Bool_t            SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bool_t hasrawdata);
+   TSQLClassInfo*    FindSQLClassInfo(const TClass* cl);
+   TSQLClassInfo*    RequestSQLClassInfo(const char* clname, Int_t version);
+   TSQLClassInfo*    RequestSQLClassInfo(const TClass* cl);
+   Bool_t            CreateClassTable(TSQLClassInfo* sqlinfo, TObjArray* colinfos);
+   Bool_t            CreateRawTable(TSQLClassInfo* sqlinfo);
+   
    Bool_t            ProduceClassSelectQuery(TStreamerInfo* info, TSQLClassInfo* sqlinfo, TString& columns, TString& tables, Int_t& tablecnt);
+   void              AddIdEntry(Long64_t tableid, Int_t subid, Int_t type,
+                                const char* name, const char* sqlname, const char* info);
+   void              ReadSQLClassInfos();
+   TString           DefineTableName(const char* clname, Int_t version, Bool_t rawtable);
+   Bool_t            HasTable(const char* name);
 
    // operations with long string table
    TString           CodeLongString(Long64_t objid, Int_t strid);
@@ -155,6 +173,9 @@ protected:
    TString           fUserName;       //! user name, used to access objects from database
   
    std::ofstream*    fLogFile;        //! log file with SQL statements
+   
+   Bool_t            fIdsTableExists; //! indicate if IdsTable exists
+   Int_t             fStmtCounter;    //! count numbers of active statements
 
 private:
    //let the compiler do the job. gcc complains when the following line is activated
diff --git a/sql/inc/TSQLObjectData.h b/sql/inc/TSQLObjectData.h
index 84a61e9817856243ead7709f8ec7629c5a13d0d9..03508d7a63b233f5c6fd32f1f31bf2110a89d5fd 100644
--- a/sql/inc/TSQLObjectData.h
+++ b/sql/inc/TSQLObjectData.h
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLObjectData.h,v 1.7 2006/05/12 08:17:02 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLObjectData.h,v 1.8 2006/05/22 08:55:58 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -48,7 +48,6 @@ public:
    const char*       GetObjClassName() const { return fClassName.Data(); }
    Version_t         GetObjVersion() const { return fVersion; }
 
-
 protected:
    Long64_t          fObjId;
    TString           fClassName;
@@ -85,7 +84,7 @@ public:
    void              AddUnpackInt(const char* tname, Int_t value);
    
    const char*       GetValue() const { return fLocatedValue; }
-   const char*       GetColumnName() const { return fLocatedField; }
+   const char*       GetLocatedField() const { return fLocatedField; }
    const char*       GetBlobPrefixName() const { return fBlobPrefixName; }
    const char*       GetBlobTypeName() const { return fBlobTypeName; }
    
diff --git a/sql/inc/TSQLStructure.h b/sql/inc/TSQLStructure.h
index 330350c0b03fa8de9c8554253ff13548c4a2b21b..a3fb87f376b9f0f0ea8ea5afd1e979053b9cd975 100644
--- a/sql/inc/TSQLStructure.h
+++ b/sql/inc/TSQLStructure.h
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLStructure.h,v 1.6 2005/12/07 14:59:57 rdm Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLStructure.h,v 1.7 2006/02/01 18:57:41 pcanal Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -38,7 +38,9 @@ class TStreamerInfo;
 class TStreamerElement;
 class TSQLFile;
 class TSqlRegistry;
+class TSqlRawBuffer;
 class TSQLObjectData;
+class TSQLClassInfo;
 class TBufferSQL2;
 
 class TSQLColumnData : public TObject {
@@ -50,7 +52,7 @@ protected:
    Bool_t      fNumeric;          //!  for numeric quotes (double quotes) are not required
 public:
    TSQLColumnData();
-   TSQLColumnData(const char* name,            
+   TSQLColumnData(const char* name,   
                   const char* sqltype, 
                   const char* value, 
                   Bool_t numeric);
@@ -68,25 +70,55 @@ public:
 
 //______________________________________________________________________
 
+class TSQLTableData : public TObject {
+  
+protected:
+   TSQLFile*      fFile;           //!
+   TSQLClassInfo* fInfo;           //!
+   TObjArray      fColumns;        //! collection of columns
+   TObjArray*     fColInfos;       //! array with TSQLClassColumnInfo, used later for TSQLClassInfo
+   
+   TString DefineSQLName(const char* fullname);
+   Bool_t HasSQLName(const char* sqlname);
+   
+public:
+   TSQLTableData(TSQLFile* f = 0, TSQLClassInfo* info = 0);
+   virtual ~TSQLTableData();
+
+   void AddColumn(const char* name, Long64_t value);
+   void AddColumn(const char* name, 
+                  const char* sqltype, 
+                  const char* value, 
+                  Bool_t numeric);
+   
+   TObjArray* TakeColInfos();
+   
+   Int_t GetNumColumns();
+   const char* GetColumn(Int_t n);
+   Bool_t IsNumeric(Int_t n);
+   
+   ClassDef(TSQLTableData, 1); // Collection of columns data for single SQL table
+};
+
+//______________________________________________________________________
+
 class TSQLStructure : public TObject {
 protected:   
 
    Bool_t           CheckNormalClassPair(TSQLStructure* vers, TSQLStructure* info);
 
    Long64_t         FindMaxObjectId();
-   void             PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const char* topname, Bool_t useblob = kFALSE);
+   void             PerformConversion(TSqlRegistry* reg, TSqlRawBuffer* blobs, const char* topname, Bool_t useblob = kFALSE);
    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);
-   Bool_t           TryConvertObjectArray(TSqlRegistry* reg, TObjArray* blobs);
+   Bool_t           StoreElementInNormalForm(TSqlRegistry* reg, TSQLTableData* columns);
+   Bool_t           TryConvertObjectArray(TSqlRegistry* reg, TSqlRawBuffer* blobs);
 
    Bool_t           StoreTObject(TSqlRegistry* reg);
    Bool_t           StoreTString(TSqlRegistry* reg);
    Bool_t           RecognizeTString(const char* &value);
 
-   void             AddCmd(TObjArray* cmds, const char* name, const char* value, const char* topname = 0, const char* ns = 0);
-
    TSQLStructure*   fParent;     //!
    Int_t            fType;       //!
    const void*      fPointer;    //!
@@ -164,32 +196,39 @@ public:
    static void      AddStrBrackets(TString &s, const char* quote);
   
    enum ESQLTypes {
-     kSqlObject       = 10001,
-     kSqlPointer      = 10002,
-     kSqlVersion      = 10003,
-     kSqlStreamerInfo = 10004,
-     kSqlClassStreamer= 10005,
-     kSqlElement      = 10006,
-     kSqlValue        = 10007,
-     kSqlArray        = 10008,
-     kSqlObjectData   = 10009,
-     kSqlCustomClass  = 10010,
-     kSqlCustomElement= 10011
+      kSqlObject       = 10001,
+      kSqlPointer      = 10002,
+      kSqlVersion      = 10003,
+      kSqlStreamerInfo = 10004,
+      kSqlClassStreamer= 10005,
+      kSqlElement      = 10006,
+      kSqlValue        = 10007,
+      kSqlArray        = 10008,
+      kSqlObjectData   = 10009,
+      kSqlCustomClass  = 10010,
+      kSqlCustomElement= 10011
    };
    
    enum ESQLColumns {
-     kColUnknown      = 0,
-     kColSimple       = 1,
-     kColSimpleArray  = 2,
-     kColParent       = 3,
-     kColObject       = 4,
-     kColObjectArray  = 5,
-     kColNormObject   = 6,
-     kColNormObjectArray = 7,
-     kColObjectPtr    = 8,
-     kColTString      = 9,
-     kColRawData      = 10
-   };   
+      kColUnknown      = 0,
+      kColSimple       = 1,
+      kColSimpleArray  = 2,
+      kColParent       = 3,
+      kColObject       = 4,
+      kColObjectArray  = 5,
+      kColNormObject   = 6,
+      kColNormObjectArray = 7,
+      kColObjectPtr    = 8,
+      kColTString      = 9,
+      kColRawData      = 10
+   };
+   
+   enum ESQLIdType {
+      kIdTable    = 0,
+      kIdRawTable = 1,
+      kIdColumn   = 2
+   }; 
+       
   
    ClassDef(TSQLStructure, 1); // Table/structure description used internally by YBufferSQL.
 };
@@ -258,6 +297,15 @@ namespace sqlio {
    extern const char* ObjectsTableIndex;
    extern const char* OT_Class;
    extern const char* OT_Version;
+   
+   extern const char* IdsTable;
+   extern const char* IdsTableIndex;
+   extern const char* IT_TableID;
+   extern const char* IT_SubID;
+   extern const char* IT_Type;
+   extern const char* IT_FullName;
+   extern const char* IT_SQLName;
+   extern const char* IT_Info;
     
    extern const char* BT_Field;
    extern const char* BT_Value;
diff --git a/sql/src/TBufferSQL2.cxx b/sql/src/TBufferSQL2.cxx
index a3415d13b0a79a732e3093887dd6bde9c2df070d..58e22cc5911ee7ad062989cbc4069be584383663 100644
--- a/sql/src/TBufferSQL2.cxx
+++ b/sql/src/TBufferSQL2.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TBufferSQL2.cxx,v 1.11 2006/05/11 10:29:45 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TBufferSQL2.cxx,v 1.12 2006/05/22 08:55:58 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -287,11 +287,11 @@ TSQLObjectData* TBufferSQL2::SqlObjectData(Long64_t objid, TSQLClassInfo* sqlinf
    }   
    
    TSQLResult *blobdata = 0;
-   TSQLStatement* stmt = fSQL->GetBlobClassDataStmt(objid, sqlinfo);
+   TSQLStatement* blobstmt = fSQL->GetBlobClassDataStmt(objid, sqlinfo);
 
-   if (stmt==0) blobdata = fSQL->GetBlobClassData(objid, sqlinfo);
+   if (blobstmt==0) blobdata = fSQL->GetBlobClassData(objid, sqlinfo);
    
-   return new TSQLObjectData(sqlinfo, objid, classdata, classrow, blobdata, stmt);
+   return new TSQLObjectData(sqlinfo, objid, classdata, classrow, blobdata, blobstmt);
 }
 
 //______________________________________________________________________________
@@ -330,6 +330,9 @@ Int_t TBufferSQL2::SqlWriteObject(const void* obj, const TClass* cl, TMemberStre
       if (value>0)
          objid = fFirstObjId + value - 1;
    }
+
+   if (gDebug>1)
+      cout << "    Find objectid = " << objid << endl;
    
    if (objid>=0) {
       Stack()->SetObjectPointer(objid);
@@ -381,7 +384,7 @@ void* TBufferSQL2::SqlReadObject(void* obj, TClass** cl, TMemberStreamer *stream
    sscanf(refid, FLong64, &objid);
 
    if (gDebug>2) 
-      Info("SqlReadObject","Starting objid = %lld column=%s", objid, fCurrentData->GetColumnName());
+      Info("SqlReadObject","Starting objid = %lld column=%s", objid, fCurrentData->GetLocatedField());
 
    if (!fCurrentData->IsBlobData() ||
        fCurrentData->VerifyDataType(sqlio::ObjectPtr,kFALSE))
@@ -442,7 +445,7 @@ void* TBufferSQL2::SqlReadObjectDirect(void* obj, TClass** cl, Long64_t objid, T
    if (gDebug>2) 
       Info("SqlReadObjectDirect","objid = %lld clname = %s ver = %d",objid, clname.Data(), version);
 
-   TSQLClassInfo* sqlinfo = fSQL->RequestSQLClassInfo(clname.Data(), version);
+   TSQLClassInfo* sqlinfo = fSQL->FindSQLClassInfo(clname.Data(), version);
 
    TClass* objClass = gROOT->GetClass(clname);
    if ((objClass==0) || (sqlinfo==0)) {
@@ -802,7 +805,7 @@ void TBufferSQL2::WorkWithClass(const char* classname, Version_t classversion)
          return;
       }
 
-      TSQLClassInfo* sqlinfo = fSQL->RequestSQLClassInfo(classname, classversion);
+      TSQLClassInfo* sqlinfo = fSQL->FindSQLClassInfo(classname, classversion);
       if (sqlinfo==0) {
          Error("WorkWithClass","Can not find table for class %s version %d", classname, classversion);
          fErrorFlag = 1;
diff --git a/sql/src/TKeySQL.cxx b/sql/src/TKeySQL.cxx
index 67d664c5c5fce1106301e4993a419c97a280fdab..97047c6eeb028732b50cb496de28ed6acc4ebafe 100644
--- a/sql/src/TKeySQL.cxx
+++ b/sql/src/TKeySQL.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TKeySQL.cxx,v 1.8 2006/05/11 10:29:45 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TKeySQL.cxx,v 1.9 2006/05/22 08:55:58 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -214,9 +214,9 @@ TObject* TKeySQL::ReadObj()
          TDirectory *dir = (TDirectory*) tobj;
          dir->SetName(GetName());
          dir->SetTitle(GetTitle());
-         //dir->SetSeekDir(GetDBKeyId());
-         dir->ReadKeys();
+         dir->SetSeekDir(GetDBKeyId());
          dir->SetMother(fMotherDir);
+         dir->ReadKeys();
          fMotherDir->Append(dir);
       }
    }
diff --git a/sql/src/TSQLClassInfo.cxx b/sql/src/TSQLClassInfo.cxx
index 1a9d7b9cd609f1411a3635c88275e55e17047894..12985a46697cae38f31c53caaef75e31bcd7ba2e 100644
--- a/sql/src/TSQLClassInfo.cxx
+++ b/sql/src/TSQLClassInfo.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLClassInfo.cxx,v 1.2 2005/11/22 20:42:36 pcanal Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLClassInfo.cxx,v 1.3 2005/12/07 14:59:57 rdm Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -14,7 +14,7 @@
 // TSQLClassInfo class containes info about tables specific to one class and
 // version. It provides names of table for that class. For each version of 
 // class not more than two tables can exists. Normal table has typically
-// name like TH1_ver4 and additional table has name like TH1_streamer_ver4
+// name like TH1_ver4 and additional table has name like TH1_raw4
 // List of this objects are kept by TSQLFile class
 //
 //________________________________________________________________________
@@ -23,6 +23,38 @@
 
 #include "TObjArray.h"
 
+
+ClassImp(TSQLClassColumnInfo)
+
+//______________________________________________________________________________
+TSQLClassColumnInfo::TSQLClassColumnInfo() :
+   TObject(),
+   fName(),
+   fSQLName(),
+   fSQLType()
+{
+   // default constructor 
+}
+
+//______________________________________________________________________________
+TSQLClassColumnInfo::TSQLClassColumnInfo(const char* name,
+                                         const char* sqlname,
+                                         const char* sqltype) :
+   TObject(),
+   fName(name),
+   fSQLName(sqlname),
+   fSQLType(sqltype)
+{
+   // normal constructor 
+}
+                     
+//______________________________________________________________________________
+TSQLClassColumnInfo::~TSQLClassColumnInfo()
+{
+   // destructor
+}
+
+
 ClassImp(TSQLClassInfo)
 
 //______________________________________________________________________________
@@ -30,6 +62,7 @@ TSQLClassInfo::TSQLClassInfo() :
    TObject(),
    fClassName(),
    fClassVersion(0),
+   fClassId(0),
    fClassTable(),
    fRawTable(),
    fColumns(0),
@@ -37,21 +70,24 @@ TSQLClassInfo::TSQLClassInfo() :
 {
 // default constructor
 }
-  
+
 //______________________________________________________________________________
-TSQLClassInfo::TSQLClassInfo(const char* classname, Int_t version) : 
+TSQLClassInfo::TSQLClassInfo(Long64_t classid,
+                             const char* classname, 
+                             Int_t version) : 
    TObject(),
    fClassName(classname),
    fClassVersion(version),
+   fClassId(classid),
    fClassTable(),
    fRawTable(),
    fColumns(0),
    fRawtableExist(kFALSE)
 {
-// normal constructor of TSQLClassInfo class
-// Sets names of tables, which are used for that version of class    
+   // normal constructor of TSQLClassInfo class
+   // Sets names of tables, which are used for that version of class    
    fClassTable.Form("%s_ver%d", classname, version);
-   fRawTable.Form("%s_streamer_ver%d", classname, version);
+   fRawTable.Form("%s_raw%d", classname, version);
 }
    
 //______________________________________________________________________________
@@ -63,7 +99,6 @@ TSQLClassInfo::~TSQLClassInfo()
       fColumns->Delete();  
       delete fColumns; 
    }
-   
 }
 
 //______________________________________________________________________________
@@ -86,3 +121,28 @@ void TSQLClassInfo::SetTableStatus(TObjArray* columns, Bool_t israwtable)
    SetColumns(columns); 
    fRawtableExist = israwtable;
 }
+
+//______________________________________________________________________________
+Int_t TSQLClassInfo::FindColumn(const char* name, Bool_t sqlname)
+{
+   // Search for column of that name
+   // Can search either for full column name (sqlname = kFALSE, default)
+   // or for name, used as column name (sqlname = kTRUE)
+   // Return index of column in list (-1 if not found)
+
+   if ((name==0) || (fColumns==0)) return -1;
+   
+   TIter next(fColumns);
+
+   TSQLClassColumnInfo* col = 0;
+   
+   Int_t indx = 0;
+   
+   while ((col = (TSQLClassColumnInfo*) next()) != 0) {
+      const char* colname = sqlname ? col->GetSQLName() : col->GetName();
+      if (strcmp(colname, name)==0) return indx;
+      indx++;
+   }
+   
+   return -1;
+}
diff --git a/sql/src/TSQLFile.cxx b/sql/src/TSQLFile.cxx
index a535168949991dd0d5c2e2c4d57b34e184cb44a9..04351fd15b40d0f8b401eb2de44bcc1c5380e6ef 100644
--- a/sql/src/TSQLFile.cxx
+++ b/sql/src/TSQLFile.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLFile.cxx,v 1.10 2006/05/22 08:55:58 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLFile.cxx,v 1.11 2006/05/23 06:16:27 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -15,17 +15,17 @@
 // "transparent" access to SQL data base via standard TFile interface.
 //
 // The main approach that each class (but not each object) has one or two tables
-// with names like $(CLASSNAME)_ver$(VERSION) and $(CLASSNAME)_streamer_ver$(VERSION)
-// For example: TAxis_ver8 or TList_streamer_ver5
+// with names like $(CLASSNAME)_ver$(VERSION) and $(CLASSNAME)_raw$(VERSION)
+// For example: TAxis_ver8 or TList_raw5
 // Second kind of tables appears, when some of class members can not be converted to
 // normalized form or when class has custom streamer.
-// For instance, for TH1 class two tables are required: TH1_ver4 and TH1_streamer_ver4
+// For instance, for TH1 class two tables are required: TH1_ver4 and TH1_raw4
 // Most of memebers are stored in TH1_ver4 table columnwise, and only memeber:
 //
 //  Double_t*  fBuffer;  //[fBufferSize]
 //
 // can not be represented as column while size of array is not known apriory.
-// Therefore, fBuffer will be written as list of values in TH1_streamer_ver4 table.
+// Therefore, fBuffer will be written as list of values in TH1_raw4 table.
 //
 // All objects, stored in the DB, will be registered in table "ObjectsTable".
 // In this there are following columns:
@@ -172,6 +172,7 @@
 #include "TBrowser.h"
 #include "TObjArray.h"
 #include "TObjString.h"
+#include "TList.h"
 #include "TArrayC.h"
 #include "TStreamerInfo.h"
 #include "TStreamerElement.h"
@@ -180,6 +181,8 @@
 #include "TClass.h"
 
 #include "TSQLServer.h"
+#include "TSQLTableInfo.h"
+#include "TSQLColumnInfo.h"
 #include "TSQLStatement.h"
 #include "TSQLResult.h"
 #include "TSQLRow.h"
@@ -257,7 +260,7 @@ const char* oracle_BasicTypes[20] = {
 
 const char* oracle_OtherTypes[13] = {
 "VARCHAR(1000)",    // smallest text
-"4095",             // maximum size of smallest text
+"1000",             // maximum size of smallest text
 "VARCHAR(4000)",    // biggest size text, CLOB is not yet supported by TOracleRow
 "VARCHAR(50)",      // date & time
 "\"",               // quote for identifier like table name or column name
@@ -271,111 +274,6 @@ const char* oracle_OtherTypes[13] = {
 ""                  // default tables types, used only for MySQL tables
 };
 
-// ******************************************************************
-
-// these are two class to produce deep copy of sql result tables
-// introduced to overcome Oracle problem
-
-class TSQLRowCopy : public TSQLRow {
-
-protected:
-   TObjArray fFields;
-
-public:
-   TSQLRowCopy(TSQLRow* res, Int_t nfields) :
-      TSQLRow(),
-      fFields()
-   {
-      for(Int_t n=0;n<nfields;n++) {
-         const char* value = res->GetField(n);
-         fFields.Add(new TObjString(value));
-      }
-   }
-
-   virtual ~TSQLRowCopy()
-   {
-   }
-
-   virtual void        Close(Option_t *option="")
-   {
-      fFields.Delete(option);
-   }
-
-   virtual ULong_t     GetFieldLength(Int_t field)
-   {
-      const char * value = GetField(field);
-      if ((value==0) || (*value==0)) return 0;
-      return strlen(value);
-   }
-
-   virtual const char *GetField(Int_t field)
-   {
-      if ((field<0) || (field>fFields.GetLast())) return 0;
-      return fFields[field]->GetName();
-   }
-};
-
-class TSQLResultCopy : public TSQLResult {
-protected:
-   TObjArray    fRows;
-   TObjArray    fNames;
-   Int_t        fCounter;
-
-public:
-   TSQLResultCopy(TSQLResult* res) :
-      TSQLResult(),
-      fRows(),
-      fNames(),
-      fCounter(0)
-   {
-      Int_t nfields = res->GetFieldCount();
-
-      for (Int_t n=0;n<nfields;n++) {
-         const char* name = res->GetFieldName(n);
-         fNames.Add(new TObjString(name));
-      }
-
-      fRowCount = 0;
-      TSQLRow* row = res->Next();
-      while (row!=0) {
-         fRowCount++;
-         fRows.Add(new TSQLRowCopy(row, nfields));
-         delete row;
-         row = res->Next();
-      }
-
-      delete res;
-   }
-
-   virtual ~TSQLResultCopy()
-   {
-   }
-
-   virtual void   Close(Option_t* option="")
-   {
-      fRows.Delete(option);
-      fNames.Delete(option);
-   }
-
-   virtual Int_t       GetFieldCount()
-   {
-      return fNames.GetLast() + 1;
-   }
-
-   virtual const char *GetFieldName(Int_t field)
-   {
-      if ((field<0) || (field>fNames.GetLast())) return 0;
-      return fNames[field]->GetName();
-   }
-
-   virtual TSQLRow* Next()
-   {
-      if (fCounter>fRows.GetLast()) return 0;
-      TSQLRow* curr = (TSQLRow*) fRows.At(fCounter++);
-      fRows.Remove(curr); // not make a copy, just remove from buffer, cannot use again
-      return curr;
-   }
-};
 
 //______________________________________________________________________________
 TSQLFile::TSQLFile() :
@@ -394,9 +292,11 @@ TSQLFile::TSQLFile() :
    fBasicTypes(0),
    fOtherTypes(0),
    fUserName(),
-   fLogFile(0)
+   fLogFile(0),
+   fIdsTableExists(kFALSE)
 {
    // default TSQLFile constructor
+   SetBit(kBinaryFile, kFALSE);
 }
 
 //______________________________________________________________________________
@@ -416,7 +316,8 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const
    fBasicTypes(mysql_BasicTypes),
    fOtherTypes(mysql_OtherTypes),
    fUserName(user),
-   fLogFile(0)
+   fLogFile(0),
+   fIdsTableExists(kFALSE)
 {
    // Connects to SQL server with provided arguments.
    // If the constructor fails in any way IsZombie() will
@@ -477,6 +378,7 @@ TSQLFile::TSQLFile(const char* dbname, Option_t* option, const char* user, const
    fProcessIDs = 0;
    fNProcessIDs= 0;
    fSeekDir    = sqlio::Ids_RootDir;
+   SetBit(kBinaryFile, kFALSE);
 
    fOption = option;
    fOption.ToUpper();
@@ -917,7 +819,7 @@ void TSQLFile::WriteHeader()
 {
    // Write file info like configurations, title, UUID and other
       
-//   WriteSpecialObject(sqlio::Ids_TSQLFile, this, GetName(), GetTitle());
+   WriteSpecialObject(sqlio::Ids_TSQLFile, this, GetName(), GetTitle());
 }
 
 //______________________________________________________________________________
@@ -982,7 +884,7 @@ Bool_t TSQLFile::WriteSpecialObject(Long64_t keyid, TObject* obj, const char* na
 //______________________________________________________________________________
 TObject* TSQLFile::ReadSpecialObject(Long64_t keyid, TObject* obj)
 {
-// Read data of special kind of objects
+   // Read data of special kind of objects
 
    TKeySQL* key = 0;
 
@@ -996,7 +898,7 @@ TObject* TSQLFile::ReadSpecialObject(Long64_t keyid, TObject* obj)
    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 
+      // name should not be preserved while name of database may be changed 
       SetTitle(key->GetTitle());
    }
    
@@ -1127,14 +1029,18 @@ void TSQLFile::InitSqlDatabase(Bool_t create)
    if (len<5000) len = 5000;
    fClassIndex = new TArrayC(len);
    fClassIndex->Reset(0);
-
+   
    if (!create) {
+      
       Bool_t ok = ReadConfigurations();
 
       // read data corresponding to TSQLFile
       if (ok) {
+         ReadSQLClassInfos();
+         
          ReadStreamerInfo();
-//         ok = (ReadSpecialObject(sqlio::Ids_TSQLFile, this) != 0);  
+         
+         ok = (ReadSpecialObject(sqlio::Ids_TSQLFile, this) != 0);
       }
       
       // read list of keys   
@@ -1343,7 +1249,7 @@ TString TSQLFile::MakeSelectQuery(TClass* cl)
    // VIEWs supported by latest MySQL 5 and Oracle
    
    TString res = ""; 
-   TSQLClassInfo* sqlinfo = RequestSQLClassInfo(cl);
+   TSQLClassInfo* sqlinfo = FindSQLClassInfo(cl);
    if (sqlinfo==0) return res;
    
    TString columns, tables;
@@ -1424,7 +1330,7 @@ Bool_t TSQLFile::ProduceClassSelectQuery(TStreamerInfo* info,
          case TSQLStructure::kColParent: {
             TClass* parentcl = elem->GetClassPointer();
             ProduceClassSelectQuery(parentcl->GetStreamerInfo(),
-                                    RequestSQLClassInfo(parentcl),
+                                    FindSQLClassInfo(parentcl),
                                     columns, tables, tablecnt);
             break;  
          } 
@@ -1531,6 +1437,12 @@ TSQLResult* TSQLFile::SQLQuery(const char* cmd, Int_t flag, Bool_t* ok)
    if (gDebug>2) Info("SQLQuery",cmd);
    
    fQuerisCounter++;
+   
+   if (flag==0) {
+      Bool_t res = fSQL->Exec(cmd);
+      if (ok!=0) *ok = res;
+      return 0;
+   }
 
    TSQLResult* res = fSQL->Query(cmd);
    if (ok!=0) *ok = res!=0;
@@ -1544,6 +1456,46 @@ TSQLResult* TSQLFile::SQLQuery(const char* cmd, Int_t flag, Bool_t* ok)
    return res;
 }
 
+//______________________________________________________________________________
+Bool_t TSQLFile::SQLCanStatement()
+{
+   // Test if DB support statement and number of open statements is not exceeded
+   
+   if (fSQL==0) return kFALSE;
+   
+   if (!fSQL->IsSupportStatement()) return kFALSE;
+   
+   return kTRUE; // !IsOracle() || (fStmtCounter<15);
+}
+
+//______________________________________________________________________________
+TSQLStatement* TSQLFile::SQLStatement(const char* cmd, Int_t bufsize)
+{
+   // Produces statement for 
+   
+   if (fSQL==0) return 0;
+   
+   if (gDebug>1)
+      Info("SQLStatement",cmd);
+      
+   fStmtCounter++;
+   fQuerisCounter++; // one statement counts as one query
+   
+   return fSQL->Statement(cmd, bufsize);
+}
+   
+//______________________________________________________________________________
+void TSQLFile::SQLDeleteStatement(TSQLStatement* stmt)
+{
+   // delete statement and decrease counter
+   
+   if (stmt==0) return;
+   
+   fStmtCounter--;
+   
+   delete stmt;
+}
+
 //______________________________________________________________________________
 Bool_t TSQLFile::SQLApplyCommands(TObjArray* cmds)
 {
@@ -1563,153 +1515,14 @@ Bool_t TSQLFile::SQLApplyCommands(TObjArray* cmds)
    return ok;
 }
 
-//______________________________________________________________________________
-TObjArray* TSQLFile::SQLTablesList(const char* searchtable)
-{
-   // Produces list of tables, presented in database
-   // if searchtable!=0, looks only for this specific table
-   // list should be deleted by user afterwards
-   // P.S. Unfortunately, the TSQLServer::GetTables function is not
-   // correctly implemented for all cases,
-   // therefore special function is required.
-
-   if (fSQL==0) return 0;
-
-   TObjArray* res = 0;
-
-   if (IsOracle()) {
-      TString sqlcmd;
-      TString user = fUserName;
-      user.ToUpper();
-      sqlcmd.Form("SELECT table_name FROM all_tables WHERE owner='%s'",user.Data());
-      if (searchtable!=0) 
-         sqlcmd += ::Form(" and table_name LIKE '%s'",searchtable);
-
-      TSQLResult* tables = SQLQuery(sqlcmd.Data(), 1);
-      if (tables==0) return 0;
-      
-      TSQLRow* row = tables->Next();
-      while (row!=0) {
-         const char* tablename = row->GetField(0);
-         if (strpbrk(tablename,"$=")==0) {
-            if (res==0) res = new TObjArray;
-            res->Add(new TObjString(tablename));
-         }
-         delete row;
-         row = tables->Next();
-      }
-      delete tables;
-   } else 
-   if (IsODBC()) {
-      TSQLResult* tables = fSQL->GetTables("",searchtable);
-      if (tables==0) return 0;
-
-      TSQLRow* row = tables->Next();
-      while (row!=0) {
-         if (res==0) res = new TObjArray;
-         res->Add(new TObjString(row->GetField(2)));
-         delete row;
-         row = tables->Next();
-      }
-      delete tables;
-      
-   } else {
-      TSQLResult* tables = fSQL->GetTables(GetDataBaseName(), searchtable);
-      if (tables==0) return 0;
-
-      TSQLRow* row = tables->Next();
-      while (row!=0) {
-         if (res==0) res = new TObjArray;
-         res->Add(new TObjString(row->GetField(0)));
-         delete row;
-         row = tables->Next();
-      }
-      delete tables;
-   }
-   if (res!=0) res->SetOwner(kTRUE);
-
-   return res;
-}
-
-//______________________________________________________________________________
-TObjArray* TSQLFile::SQLTableColumns(const char* tablename)
-{
-   // produces list of columns for specified table
-   // list consist of TNamed objects with name and type for each column
-   // list should be deleted aftrewards
-   // P.S. Oracle plug-in do not provides types
-
-   if (fSQL==0) return 0;
-
-   TObjArray* res = 0;
-
-   if (IsOracle()) {
-
-//      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?");
-         if (res==0) res = new TObjArray;
-         res->Add(col);
-      }
-      delete cols;
-   } else 
-   if (IsODBC()) {
-      TSQLResult* cols = fSQL->GetColumns("", tablename);
-      if (cols==0) return 0;
-
-      TSQLRow* row = cols->Next();
-      while (row!=0) {
-         TNamed* col = new TNamed(row->GetField(3), row->GetField(5));
-         if (res==0) res = new TObjArray;
-         res->Add(col);
-         delete row;
-         row = cols->Next();
-      }
-      delete cols;
-   } else {
-      TSQLResult* cols = fSQL->GetColumns(GetDataBaseName(), tablename, "");
-
-      if (cols==0) return 0;
-
-      TSQLRow* row = cols->Next();
-      while (row!=0) {
-         TNamed* col = new TNamed(row->GetField(0), row->GetField(1));
-         if (res==0) res = new TObjArray;
-         res->Add(col);
-         delete row;
-         row = cols->Next();
-      }
-
-      delete cols;
-   }
-   return res;
-}
-
 //______________________________________________________________________________
 Bool_t TSQLFile::SQLTestTable(const char* tablename)
 {
    // Test, if table of specified name exists
 
-   TObjArray* list = SQLTablesList(tablename);
-
-   Bool_t res = (list!=0);
-
-   delete list;
-
-   return res;
+   if (fSQL==0) return kFALSE;
+   
+   return fSQL->HasTable(tablename);
 }
 
 //______________________________________________________________________________
@@ -1720,8 +1533,6 @@ Long64_t TSQLFile::SQLMaximumValue(const char* tablename, const char* columnname
 
    if (fSQL==0) return -1;
 
-   if (fSQL==0) return -1;
-
    if (gDebug>2)
       Info("SQLMaximumValue","Requests for %s column %s", tablename, columnname);
 
@@ -1756,7 +1567,9 @@ void TSQLFile::SQLDeleteAllTables()
 {
    // Delete all tables in database
 
-   TObjArray* tables = SQLTablesList();
+   if (fSQL==0) return;
+
+   TList* tables = fSQL->GetTablesList();
    if (tables==0) return;
 
    TString sqlcmd;
@@ -1776,9 +1589,7 @@ Bool_t TSQLFile::SQLStartTransaction()
 {
    // Start SQL transaction.
    
-   Bool_t ok;
-   SQLQuery("START TRANSACTION", 0, &ok);
-   return ok;
+   return fSQL ? fSQL->StartTransaction() : kFALSE;
 }
 
 //______________________________________________________________________________
@@ -1786,9 +1597,7 @@ Bool_t TSQLFile::SQLCommit()
 {
    // Commit SQL transaction
 
-   Bool_t ok;
-   SQLQuery("COMMIT", 0, &ok);
-   return ok;
+   return fSQL ? fSQL->Commit() : kFALSE;
 }
 
 //______________________________________________________________________________
@@ -1796,9 +1605,20 @@ Bool_t TSQLFile::SQLRollback()
 {
    // Rollback all SQL operations, done after start transaction
 
-   Bool_t ok;
-   SQLQuery("ROLLBACK", 0, &ok);
-   return ok;
+   return fSQL ? fSQL->Rollback() : kFALSE;
+}
+
+//______________________________________________________________________________
+Int_t TSQLFile::SQLMaxIdentifierLength()
+{
+   // returns maximum allowed length of identifiers
+   
+   Int_t maxlen = fSQL==0 ? 32 : fSQL->GetMaxIdentifierLength();
+   
+   // lets exclude absolute ubnormal data
+   if (maxlen<10) maxlen = 10;
+
+   return maxlen;
 }
 
 //______________________________________________________________________________
@@ -1831,25 +1651,26 @@ void TSQLFile::DeleteKeyFromDB(Long64_t keyid)
   
    // 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,
+      TIter iter(fSQLClassInfos);
+      TSQLClassInfo* info = 0;
+      TString querymask, query;
+      querymask.Form("DELETE FROM %s%s%s WHERE %s%s%s BETWEEN %lld AND %lld", 
+                     quote, "%s", quote,
                      quote, SQLObjectIdColumn(), quote, 
                      minid, maxid);
-         SQLQuery(query.Data());
+      
+      while ((info = (TSQLClassInfo*) iter()) !=0 ) {
+
+         if (info->IsClassTableExist()) {
+            query.Form(querymask.Data(), info->GetClassTableName());
+            SQLQuery(query.Data());
+         }
+         
+         if (info->IsRawTableExist()) {
+            query.Form(querymask.Data(), info->GetRawTableName());
+            SQLQuery(query.Data());
+         }
       }
-   
-      delete tables;
    }
 
    sqlcmd.Form("DELETE FROM %s%s%s WHERE %s%s%s=%lld", quote, sqlio::ObjectsTable, quote, quote, SQLKeyIdColumn(), quote, keyid);
@@ -1921,13 +1742,21 @@ Bool_t TSQLFile::UpdateKeyData(TKeySQL* key)
    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",
+   
+   TString keyname = key->GetName();
+   TString keytitle = key->GetTitle();
+   TString keydatime = key->GetDatime().AsSQLString();
+   
+   TSQLStructure::AddStrBrackets(keyname, valuequote);
+   TSQLStructure::AddStrBrackets(keytitle, valuequote);
+   TSQLStructure::AddStrBrackets(keydatime, valuequote);
+   
+   sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s, %s%s%s=%d 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, sqlio::KT_Name, quote, keyname.Data(),
+                quote, sqlio::KT_Title, quote, keytitle.Data(),
+                quote, sqlio::KT_Datetime, quote, keydatime.Data(),
+                quote, sqlio::KT_Cycle, quote, key->GetCycle(),
                 quote, SQLKeyIdColumn(), quote, key->GetDBKeyId());
 
    Bool_t ok = kTRUE;
@@ -1957,7 +1786,7 @@ Long64_t TSQLFile::DefineNextKeyId()
 //______________________________________________________________________________
 TSQLClassInfo* TSQLFile::FindSQLClassInfo(const char* clname, Int_t version)
 {
-   // return (if exists) TSQLClassInfo for specified class and version
+   // return (if exists) TSQLClassInfo for specified class name and version
 
    if (fSQLClassInfos==0) return 0;
 
@@ -1972,26 +1801,38 @@ TSQLClassInfo* TSQLFile::FindSQLClassInfo(const char* clname, Int_t version)
 }
 
 //______________________________________________________________________________
-TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const char* clname, Int_t version, Bool_t force)
+TSQLClassInfo* TSQLFile::FindSQLClassInfo(const TClass* cl)
+{
+   // return (if exists) TSQLClassInfo for specified class
+
+   return FindSQLClassInfo(cl->GetName(), cl->GetClassVersion());
+}
+
+//______________________________________________________________________________
+TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const char* clname, Int_t version)
 {
    // search in database tables for specified class and return TSQLClassInfo object
 
    TSQLClassInfo* info = FindSQLClassInfo(clname, version);
-   if (!force && (info!=0)) return info;
+   if (info!=0) return info;
 
    if (fSQL==0) return 0;
+   
+   Long64_t maxid = 0;
 
-   if (info==0) info = new TSQLClassInfo(clname, version);
-
-   TObjArray* columns = 0;
-
-   // first check if class table is exist
-   if (SQLTestTable(info->GetClassTableName()))
-      columns = SQLTableColumns(info->GetClassTableName());
+   if (fSQLClassInfos!=0) {
+      TIter iter(fSQLClassInfos);
+      TSQLClassInfo* info = 0;
+      while ((info = (TSQLClassInfo*) iter()) !=0 ) {
+         if (info->GetClassId()>maxid)
+            maxid = info->GetClassId();
+      }
+   }
 
-   Bool_t israwtable = SQLTestTable(info->GetRawTableName());
+   info = new TSQLClassInfo(maxid+1, clname, version);
 
-   info->SetTableStatus(columns, israwtable);
+   info->SetClassTableName(DefineTableName(clname, version, kFALSE));
+   info->SetRawTableName(DefineTableName(clname, version, kTRUE));
 
    if (fSQLClassInfos==0) fSQLClassInfos = new TList;
    fSQLClassInfos->Add(info);
@@ -2000,159 +1841,368 @@ TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const char* clname, Int_t version,
 }
 
 //______________________________________________________________________________
-TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const TClass* cl, Bool_t force)
+TString TSQLFile::DefineTableName(const char* clname, Int_t version, Bool_t rawtable)
 {
-   // search in database tables for specified class and return TSQLClassInfo object
+   // proposes table name for class
+   
+   Int_t maxlen = SQLMaxIdentifierLength();
 
-   return RequestSQLClassInfo(cl->GetName(), cl->GetClassVersion(), force);
-}
+   TString res;
 
-//______________________________________________________________________________
-Bool_t TSQLFile::SyncSQLClassInfo(TSQLClassInfo* sqlinfo, TObjArray* columns, Bool_t hasrawdata)
-{
-   // Synchronise TSQLClassInfo structure with specified columns list and
-   // create/delete appropriate tables in database
+   const char *suffix = rawtable ? "_raw" : "_ver";
 
-   if (sqlinfo==0) return kFALSE;
+   res.Form("%s%s%d", clname, suffix, version);
 
-   if (gDebug>2)
-      Info("SyncSQLClassInfo", sqlinfo->GetName());
+   if ((res.Length() <= maxlen) && !HasTable(res.Data()))
+      return res;
+   
+   TString scnt;
+   
+   Int_t len = strlen(clname);
+   Int_t cnt = version;
+   if (cnt>100) cnt = 0; // do not start with the biggest values
+   
+   do {
+      scnt.Form("%d%s",cnt, suffix);
+      Int_t numlen = scnt.Length();
+      if (numlen>=maxlen-2) break;
+      
+      res = clname;
+      
+      if (len + numlen > maxlen) 
+         res.Resize(maxlen - numlen);
+      
+      res+=scnt;
+      
+      if (!HasTable(res.Data())) return res;
+      
+      cnt++;
+      
+   } while (cnt<10000);
 
-   const char* quote = SQLIdentifierQuote();
+   Error("DefineTableName","Cannot produce table name for class %s ver %d", clname, version);
+   res.Form("%s%s%d", clname, suffix, version);
 
-   if (sqlinfo->IsClassTableExist() && (columns==0)) {
-      TString sqlcmd;
-      sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlinfo->GetClassTableName(), quote);
-      SQLQuery(sqlcmd.Data());
+   return res;   
+}
+
+//______________________________________________________________________________
+Bool_t TSQLFile::HasTable(const char* name)
+{
+   // test if table name exists
 
-      sqlinfo->SetColumns(0);
+   if (fSQLClassInfos==0) return kFALSE;
+   
+   TIter iter(fSQLClassInfos);
+   TSQLClassInfo* info = 0;
+   while ((info = (TSQLClassInfo*) iter()) !=0 ) {
+      if (strcmp(info->GetClassTableName(), name)==0) return kTRUE;
+      if (strcmp(info->GetRawTableName(), name)==0) return kTRUE;
    }
+   
+   return kFALSE;
+}
 
-   if (!sqlinfo->IsClassTableExist() && (columns!=0)) {
+//______________________________________________________________________________
+TSQLClassInfo* TSQLFile::RequestSQLClassInfo(const TClass* cl)
+{
+   // search in database tables for specified class and return TSQLClassInfo object
 
-      TString sqlcmd;
-      sqlcmd.Form("CREATE TABLE %s%s%s (", 
-                   quote, sqlinfo->GetClassTableName(), quote);
-
-      TObjArray* newcolumns = new TObjArray();
-      TIter iter(columns);
-      TSQLColumnData* col;
-      Bool_t first = kTRUE;
-      Bool_t forcequote = IsOracle();
-      while ((col=(TSQLColumnData*)iter())!=0) {
-         if (!first) sqlcmd+=", "; else first = false;
-
-         const char* colname = col->GetName();
-         if ((strpbrk(colname,"[:.]<>")!=0) || forcequote) {
-            sqlcmd += quote;
-            sqlcmd += colname;
-            sqlcmd += quote;
-            sqlcmd += " ";
-         } else {
-            sqlcmd += colname,
-               sqlcmd += " ";
+   return RequestSQLClassInfo(cl->GetName(), cl->GetClassVersion());
+}
+
+//______________________________________________________________________________
+void TSQLFile::ReadSQLClassInfos()
+{
+   // Read all class infos from IdsTable
+   
+   if (fSQL==0) return;
+   
+   fIdsTableExists = SQLTestTable(sqlio::IdsTable);
+   
+   if (!fIdsTableExists) return;
+   
+   TString sqlcmd;
+   const char* quote = SQLIdentifierQuote();
+   
+   sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s",
+                quote, sqlio::IdsTable, quote,
+                quote, sqlio::IT_Type, quote, TSQLStructure::kIdTable,
+                quote, sqlio::IT_TableID, quote);
+                
+   TSQLResult* res = SQLQuery(sqlcmd.Data(), 1);
+   
+   TSQLRow* row = 0;
+   
+   if (res!=0) 
+      while ((row = res->Next())!=0) {
+         Long64_t tableid = sqlio::atol64(row->GetField(0));
+         Int_t version = atoi(row->GetField(1));
+         
+         const char* classname = row->GetField(3);
+         const char* classtable = row->GetField(4);
+        
+         TSQLClassInfo* info = new TSQLClassInfo(tableid, classname, version);
+         info->SetClassTableName(classtable);
+     
+         if (fSQLClassInfos==0) fSQLClassInfos = new TList;
+         fSQLClassInfos->Add(info);
+        
+         delete row;
+      }
+   delete res;  
+   
+   
+   TIter next(fSQLClassInfos);
+   TSQLClassInfo* info = 0;
+   
+   while ((info = (TSQLClassInfo*) next()) != 0) {
+      sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %lld ORDER BY %s%s%s",
+                   quote, sqlio::IdsTable, quote,
+                   quote, sqlio::IT_TableID, quote, info->GetClassId(),
+                   quote, sqlio::IT_SubID, quote);
+      res = SQLQuery(sqlcmd.Data(), 1);
+      
+      TObjArray* cols = 0;
+      
+      if (res!=0) 
+         while ((row = res->Next())!=0) {
+            
+            Int_t typ = atoi(row->GetField(2));
+
+            const char* fullname = row->GetField(3);
+            const char* sqlname = row->GetField(4);
+            const char* info = row->GetField(5);
+
+            if (typ==TSQLStructure::kIdColumn) {
+                if (cols==0) cols = new TObjArray;
+                cols->Add(new TSQLClassColumnInfo(fullname, sqlname, info));
+            }
+            
+            delete row;
          }
+      
+      delete res;
+      
+      info->SetColumns(cols);
+   }
+   
+   sqlcmd.Form("SELECT * FROM %s%s%s WHERE %s%s%s = %d ORDER BY %s%s%s",
+                quote, sqlio::IdsTable, quote,
+                quote, sqlio::IT_Type, quote, TSQLStructure::kIdRawTable,
+                quote, sqlio::IT_TableID, quote);
+   
+   res = SQLQuery(sqlcmd.Data(), 1);
+   
+   if (res!=0) 
+      while ((row = res->Next())!=0) {
+         Long64_t tableid = sqlio::atol64(row->GetField(0));
+         Int_t version = atoi(row->GetField(1));
+        
+         const char* classname = row->GetField(3);
+         const char* rawtable = row->GetField(4);
+         
+         TSQLClassInfo* info = FindSQLClassInfo(classname, version);
+         
+         if (info==0) {
+            info = new TSQLClassInfo(tableid, classname, version);
+            
+            if (fSQLClassInfos==0) fSQLClassInfos = new TList;
+            fSQLClassInfos->Add(info);
+         }
+         
+         info->SetRawTableName(rawtable);
+         info->SetRawExist(kTRUE);
+        
+         delete row;
+      }
+      
+   delete res;  
+}
 
-         sqlcmd += col->GetType();
 
-         newcolumns->Add(new TNamed(col->GetName(), col->GetType()));
+//______________________________________________________________________________
+void TSQLFile::AddIdEntry(Long64_t tableid, Int_t subid, Int_t type,
+                          const char* name, const char* sqlname, const char* info)
+{
+   // Add entry into IdsTable, where all tables names and columns names are listed
+   
+   if ((fSQL==0) || !IsWritable()) return;
+   
+   TString sqlcmd;
+   const char* valuequote = SQLValueQuote();
+   const char* quote = SQLIdentifierQuote();
+   
+   if (!fIdsTableExists) {
+
+      if (SQLTestTable(sqlio::IdsTable)) {
+         sqlcmd.Form("DROP TABLE %s%s%s", quote, sqlio::IdsTable, quote);
+         SQLQuery(sqlcmd.Data());
       }
-      sqlcmd += ")";
-      
-      if ((fTablesType.Length()>0)  && IsMySQL()) {
+
+      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)",
+                  quote, sqlio::IdsTable, quote,
+                  quote, sqlio::IT_TableID, quote, SQLIntType(),
+                  quote, sqlio::IT_SubID, quote, SQLIntType(),
+                  quote, sqlio::IT_Type, quote, SQLIntType(),
+                  quote, sqlio::IT_FullName, quote, SQLSmallTextType(),
+                  quote, sqlio::IT_SQLName, quote, SQLSmallTextType(),
+                  quote, sqlio::IT_Info, quote, SQLSmallTextType());
+      if ((fTablesType.Length()>0) && IsMySQL()) {
          sqlcmd +=" TYPE=";
          sqlcmd += fTablesType;
       }
-
       SQLQuery(sqlcmd.Data());
-
-      sqlinfo->SetColumns(newcolumns);
       
-      if (GetUseIndexes()>kIndexesBasic) {
-         sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I1%s ON %s%s%s (%s%s%s)",
-                     quote, sqlinfo->GetClassTableName(), quote,
-                     quote, sqlinfo->GetClassTableName(), quote,
-                     quote, SQLObjectIdColumn(), quote);
-         SQLQuery(sqlcmd.Data());    
-      }
+      fIdsTableExists = kTRUE;  
    }
 
-   SyncSQLClassInfoRawTables(sqlinfo, hasrawdata);
+   sqlcmd.Form("INSERT INTO %s%s%s VALUES (%lld, %d, %d, %s%s%s, %s%s%s, %s%s%s)",
+               quote, sqlio::IdsTable, quote,
+               tableid, subid, type,
+               valuequote, name, valuequote,
+               valuequote, sqlname, valuequote,
+               valuequote, info, valuequote);
 
-/*
-   if (hasrawdata && !sqlinfo->IsRawTableExist()) {
-      TString sqlcmd;
+   SQLQuery(sqlcmd.Data());
+}                          
 
-      sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)",
-                  quote, sqlinfo->GetRawTableName(), quote,
-                  quote, SQLObjectIdColumn(), quote, SQLIntType(),
-                  quote, SQLRawIdColumn(), quote, SQLIntType(),
-                  sqlio::BT_Field, SQLSmallTextType(),
-                  sqlio::BT_Value, SQLSmallTextType());
-                  
-      if ((fTablesType.Length()>0) && IsMySQL()) {
-         sqlcmd +=" TYPE=";
-         sqlcmd += fTablesType;
+//______________________________________________________________________________
+Bool_t TSQLFile::CreateClassTable(TSQLClassInfo* sqlinfo, TObjArray* colinfos)
+{
+   // Create normal class table if required
+
+   if (sqlinfo==0) return kFALSE;
+   
+   // this is normal situation, when no extra column infos was created when not necessary
+   if (colinfos==0) return sqlinfo->IsClassTableExist();
+
+   if (sqlinfo->IsClassTableExist()) {
+      if (colinfos!=0) {
+         colinfos->Delete();
+         delete colinfos;
+         //Error("CreateClassTable","Why colinfos for table %s", sqlinfo->GetClassTableName());
       }
+      return kTRUE;
+   }
 
-      SQLQuery(sqlcmd.Data());
-      sqlinfo->SetRawExist(kTRUE);
-      
-      if (GetUseIndexes()>kIndexesClass) {
-         sqlcmd.Form("CREATE UNIQUE INDEX %s%s_Index%s ON %s%s%s (%s%s%s, %s%s%s)",
-                     quote, sqlinfo->GetRawTableName(), quote,
-                     quote, sqlinfo->GetRawTableName(), quote,
-                     quote, SQLObjectIdColumn(), quote,
-                     quote, SQLRawIdColumn(), quote);
-         SQLQuery(sqlcmd.Data());    
+   if (gDebug>2)
+      Info("CreateClassTable", "cl:%s", sqlinfo->GetName());
+
+   const char* quote = SQLIdentifierQuote();
+
+   AddIdEntry(sqlinfo->GetClassId(), 
+              sqlinfo->GetClassVersion(),
+              TSQLStructure::kIdTable,
+              sqlinfo->GetName(),
+              sqlinfo->GetClassTableName(),
+              "Main class table");
+
+   TString sqlcmd;
+   sqlcmd.Form("CREATE TABLE %s%s%s (", 
+                quote, sqlinfo->GetClassTableName(), quote);
+
+   TIter iter(colinfos);
+   TSQLClassColumnInfo* col;
+   Bool_t first = kTRUE;
+   Bool_t forcequote = IsOracle();
+   Int_t colid = 0;
+   while ((col=(TSQLClassColumnInfo*)iter())!=0) {
+      if (!first) sqlcmd+=", "; else first = false;
+
+      const char* colname = col->GetSQLName();
+      if ((strpbrk(colname,"[:.]<>")!=0) || forcequote) {
+         sqlcmd += quote;
+         sqlcmd += colname;
+         sqlcmd += quote;
+         sqlcmd += " ";
+      } else {
+         sqlcmd += colname,
+         sqlcmd += " ";
       }
 
+      sqlcmd += col->GetSQLType();
+
+      AddIdEntry(sqlinfo->GetClassId(), 
+                 colid++,
+                 TSQLStructure::kIdColumn,
+                 col->GetName(),
+                 col->GetSQLName(),
+                 col->GetSQLType());
+   }
+   sqlcmd += ")";
+   
+   if ((fTablesType.Length()>0)  && IsMySQL()) {
+      sqlcmd +=" TYPE=";
+      sqlcmd += fTablesType;
+   }
+
+   SQLQuery(sqlcmd.Data());
+
+   sqlinfo->SetColumns(colinfos);
+   
+   if (GetUseIndexes()>kIndexesBasic) {
+      
+      TString indxname = sqlinfo->GetClassTableName();
+      indxname.ReplaceAll("_ver","_i1x");
+      
+      sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I1%s ON %s%s%s (%s%s%s)",
+                  quote, indxname.Data(), quote,
+                  quote, sqlinfo->GetClassTableName(), quote,
+                  quote, SQLObjectIdColumn(), quote);
+      SQLQuery(sqlcmd.Data());    
    }
-*/
 
    return kTRUE;
 }
 
 //______________________________________________________________________________
-Bool_t TSQLFile::SyncSQLClassInfoRawTables(TSQLClassInfo* sqlinfo, Bool_t hasrawdata)
+Bool_t TSQLFile::CreateRawTable(TSQLClassInfo* sqlinfo)
 {
-   // creates table for class raw data, if it is not exists
-    
    if (sqlinfo==0) return kFALSE;
+   
+   if (sqlinfo->IsRawTableExist()) return kTRUE;
 
    const char* quote = SQLIdentifierQuote();
 
-   if (hasrawdata && !sqlinfo->IsRawTableExist()) {
-       if (gDebug>2)
-         Info("SyncSQLClassInfoRawTables", sqlinfo->GetName());
+   if (gDebug>2)
+      Info("CreateRawTable", sqlinfo->GetName());
 
-      TString sqlcmd;
+   TString sqlcmd;
 
-      sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)",
-                  quote, sqlinfo->GetRawTableName(), quote,
-                  quote, SQLObjectIdColumn(), quote, SQLIntType(),
-                  quote, SQLRawIdColumn(), quote, SQLIntType(),
-                  sqlio::BT_Field, SQLSmallTextType(),
-                  sqlio::BT_Value, SQLSmallTextType());
-                  
-      if ((fTablesType.Length()>0) && IsMySQL()) {
-         sqlcmd +=" TYPE=";
-         sqlcmd += fTablesType;
-      }
+   sqlcmd.Form("CREATE TABLE %s%s%s (%s%s%s %s, %s%s%s %s, %s %s, %s %s)",
+               quote, sqlinfo->GetRawTableName(), quote,
+               quote, SQLObjectIdColumn(), quote, SQLIntType(),
+               quote, SQLRawIdColumn(), quote, SQLIntType(),
+               sqlio::BT_Field, SQLSmallTextType(),
+               sqlio::BT_Value, SQLSmallTextType());
+               
+   if ((fTablesType.Length()>0) && IsMySQL()) {
+      sqlcmd +=" TYPE=";
+      sqlcmd += fTablesType;
+   }
 
-      SQLQuery(sqlcmd.Data());
-      sqlinfo->SetRawExist(kTRUE);
-      
-      if (GetUseIndexes()>kIndexesClass) {
-         sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I2%s ON %s%s%s (%s%s%s, %s%s%s)",
-                     quote, sqlinfo->GetClassTableName(), quote,
-                     quote, sqlinfo->GetRawTableName(), quote,
-                     quote, SQLObjectIdColumn(), quote,
-                     quote, SQLRawIdColumn(), quote);
-         SQLQuery(sqlcmd.Data());    
-      }
+   SQLQuery(sqlcmd.Data());
+   sqlinfo->SetRawExist(kTRUE);
+   
+   if (GetUseIndexes()>kIndexesClass) {
+      TString indxname = sqlinfo->GetClassTableName();
+      indxname.ReplaceAll("_ver","_i2x");
 
+      sqlcmd.Form("CREATE UNIQUE INDEX %s%s_I2%s ON %s%s%s (%s%s%s, %s%s%s)",
+                  quote, indxname.Data(), quote,
+                  quote, sqlinfo->GetRawTableName(), quote,
+                  quote, SQLObjectIdColumn(), quote,
+                  quote, SQLRawIdColumn(), quote);
+      SQLQuery(sqlcmd.Data());    
    }
+   
+   AddIdEntry(sqlinfo->GetClassId(), 
+              sqlinfo->GetClassVersion(),
+              TSQLStructure::kIdRawTable,
+              sqlinfo->GetName(),
+              sqlinfo->GetRawTableName(),
+              "Raw data class table");
 
    return kTRUE;
 }
@@ -2533,3 +2583,135 @@ const char* TSQLFile::SQLIntType() const
    return SQLCompatibleType(TStreamerInfo::kInt);
 }
 
+//______________________________________________________________________________
+Long64_t TSQLFile::DirCreateEntry(TDirectory* dir)
+{
+   // Create entry for directory in database
+
+   TDirectory* mother = dir->GetMotherDir();
+   if (mother==0) mother = this;
+    
+   // key will be added to mother directory 
+   TKeySQL* key = new TKeySQL(mother, dir, dir->GetName(), dir->GetTitle());
+   
+   return key->GetDBKeyId();
+}
+
+//______________________________________________________________________________
+Int_t TSQLFile::DirReadKeys(TDirectory* dir)
+{
+   // Read directory list of keys from database
+
+   // First delete all old keys 
+   dir->GetListOfKeys()->Delete(); 
+
+   if (gDebug>2) 
+      Info("DirReadKeys","dir = %s id = %d", dir->GetName(), dir->GetSeekDir());
+
+   return StreamKeysForDirectory(dir, kFALSE);
+}
+
+//______________________________________________________________________________
+void TSQLFile::DirWriteKeys(TDirectory* dir)
+{
+   // Write directory keys list to database 
+    
+   StreamKeysForDirectory(dir, kTRUE);   
+}
+
+//______________________________________________________________________________
+void TSQLFile::DirWriteHeader(TDirectory* dir)
+{
+   // Update dir header in the file
+   
+   TSQLClassInfo* sqlinfo = FindSQLClassInfo("TDirectory",TDirectory::Class()->GetClassVersion());
+   if (sqlinfo==0) return;
+   
+   // try to identify key with data for our directory
+   TKeySQL* key = FindSQLKey(dir->GetMotherDir(), dir->GetSeekDir());
+   if (key==0) return;
+   
+   const char* valuequote = SQLValueQuote();
+   const char* quote = SQLIdentifierQuote();
+
+   TString timeC = dir->GetCreationDate().AsSQLString();
+   TSQLStructure::AddStrBrackets(timeC, valuequote);
+   
+   TString timeM = dir->GetModificationDate().AsSQLString();
+   TSQLStructure::AddStrBrackets(timeM, valuequote);
+   
+   TString uuid = dir->GetUUID().AsString();
+   TSQLStructure::AddStrBrackets(uuid, valuequote);
+   
+   TString sqlcmd;
+   
+   TString col1name = "CreateTime";
+   TString col2name = "ModifyTime";
+   TString col3name = "UUID";
+   if (GetUseSuffixes()) {
+      col1name+=sqlio::StrSuffix;   
+      col2name+=sqlio::StrSuffix;
+      col3name+=sqlio::StrSuffix;
+   }
+
+   sqlcmd.Form("UPDATE %s%s%s SET %s%s%s=%s, %s%s%s=%s, %s%s%s=%s WHERE %s%s%s=%d",
+                quote, sqlinfo->GetClassTableName(), quote,
+                quote, col1name.Data(), quote, timeC.Data(),
+                quote, col2name.Data(), quote, timeM.Data(),
+                quote, col3name.Data(), quote, uuid.Data(),
+                quote, SQLObjectIdColumn(), quote, key->GetDBObjId());
+
+   SQLQuery(sqlcmd.Data());
+}
+
+//______________________________________________________________________________
+void TSQLFile::Streamer(TBuffer &b)
+{
+   // streamer for TSQLFile class
+   // stores only data for TDirectory
+   
+
+   TString sbuf;
+   
+   if (b.IsReading()) {
+      Version_t R__v = b.ReadVersion(0, 0);
+      b.ClassBegin(TSQLFile::Class(), R__v);
+      
+      b.ClassMember("CreateTime","TString");
+      sbuf.Streamer(b);
+      TDatime timeC(sbuf.Data());
+      fDatimeC = timeC;
+        
+      b.ClassMember("ModifyTime","TString");
+      sbuf.Streamer(b);
+      TDatime timeM(sbuf.Data());
+      fDatimeM = timeM;
+
+      b.ClassMember("UUID","TString");
+      sbuf.Streamer(b);
+      TUUID id(sbuf.Data());
+      fUUID = id;
+      
+      b.ClassEnd(TSQLFile::Class());
+   } else {
+       
+      b.WriteVersion(TSQLFile::Class());
+      
+      b.ClassBegin(TSQLFile::Class());
+      
+      b.ClassMember("CreateTime","TString");
+      sbuf = fDatimeC.AsSQLString();
+      sbuf.Streamer(b);
+         
+      b.ClassMember("ModifyTime","TString");
+      fDatimeM.Set();
+      sbuf = fDatimeM.AsSQLString();
+      sbuf.Streamer(b);
+         
+      b.ClassMember("UUID","TString");
+      sbuf = fUUID.AsString();
+      sbuf.Streamer(b);
+
+      b.ClassEnd(TSQLFile::Class());
+   }
+}
diff --git a/sql/src/TSQLObjectData.cxx b/sql/src/TSQLObjectData.cxx
index 7653019535b5d15ee2b3eafb791e3579d7a2cf6e..21735672eecc8ffcacbfba57287195c968969afa 100644
--- a/sql/src/TSQLObjectData.cxx
+++ b/sql/src/TSQLObjectData.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLObjectData.cxx,v 1.6 2006/05/11 10:29:45 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLObjectData.cxx,v 1.7 2006/05/22 08:55:58 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -15,7 +15,7 @@
 // It contains data, request from database table for one specifc
 // object for one specific class. For instance, when data for
 // class TH1 required, requests will be done to
-// TH1_ver4 and TH1_streamer_ver4 tables and result of these reuests
+// TH1_ver4 and TH1_raw4 tables and result of these requests
 // will be kept in single TSQLObjectData instance.
 //
 //________________________________________________________________________
@@ -164,9 +164,17 @@ Bool_t TSQLObjectData::LocateColumn(const char* colname, Bool_t isblob)
 
    if ((fClassData==0) || (fClassRow==0)) return kFALSE;
 
-   Int_t numfields = GetNumClassFields();
+//   Int_t numfields = GetNumClassFields();
 
-   for (Int_t ncol=1;ncol<numfields;ncol++) {
+   Int_t ncol = fInfo->FindColumn(colname, kFALSE);
+   if (ncol>0) {
+      fLocatedColumn = ncol;
+      fLocatedField = GetClassFieldName(ncol);
+      fLocatedValue = fClassRow->GetField(ncol);
+   }
+  
+
+/*   for (Int_t ncol=1;ncol<numfields;ncol++) {
       const char* fieldname = GetClassFieldName(ncol);
       if (strcmp(colname, fieldname)==0) {
          fLocatedColumn = ncol;
@@ -175,6 +183,7 @@ Bool_t TSQLObjectData::LocateColumn(const char* colname, Bool_t isblob)
          break;
       }
    }
+*/
 
    if (fLocatedField==0) return kFALSE;
 
diff --git a/sql/src/TSQLStructure.cxx b/sql/src/TSQLStructure.cxx
index 0775ac63fc2a293498b666a9541d65efaaf9d81f..b008b345db2c29b907da67cc0b053e2b6f94286a 100644
--- a/sql/src/TSQLStructure.cxx
+++ b/sql/src/TSQLStructure.cxx
@@ -1,4 +1,4 @@
-// @(#)root/sql:$Name:  $:$Id: TSQLStructure.cxx,v 1.11 2006/05/12 08:17:02 brun Exp $
+// @(#)root/sql:$Name:  $:$Id: TSQLStructure.cxx,v 1.12 2006/05/22 08:55:58 brun Exp $
 // Author: Sergey Linev  20/11/2005
 
 /*************************************************************************
@@ -88,6 +88,8 @@ namespace sqlio {
    const char* KeysTableIndex = "KeysTableIndex";
    const char* ObjectsTable   = "ObjectsTable";
    const char* ObjectsTableIndex = "ObjectsTableIndex";
+   const char* IdsTable = "IdsTable";
+   const char* IdsTableIndex = "IdsTableIndex";
    const char* StringsTable   = "StringsTable";
    const char* ConfigTable    = "Configurations";
 
@@ -106,6 +108,14 @@ namespace sqlio {
    const char* OT_Class     = "Class";
    const char* OT_Version   = "Version";
 
+   // columns in Identifiers Table
+   const char* IT_TableID   = "TableId";
+   const char* IT_SubID     = "SubId";
+   const char* IT_Type      = "Type";
+   const char* IT_FullName  = "FullName";
+   const char* IT_SQLName   = "SQLName";
+   const char* IT_Info      = "Info";
+
    // colummns in _streamer_ tables
    const char* BT_Field     = "Field";
    const char* BT_Value     = "Value";
@@ -194,19 +204,171 @@ TSQLColumnData::~TSQLColumnData()
    // TSQLColumnData destructor
 }
 
+
+ClassImp(TSQLTableData);
+
 //________________________________________________________________________
+TSQLTableData::TSQLTableData(TSQLFile* f, TSQLClassInfo* info) : 
+   TObject(),
+   fFile(f),
+   fInfo(info),
+   fColumns(),
+   fColInfos(0)
+{
+   // normal constructor
+   
+   if (!info->IsClassTableExist()) 
+      fColInfos = new TObjArray;
+}
 
-ClassImp(TSQLStructure)
+//________________________________________________________________________
+TSQLTableData::~TSQLTableData()
+{
+   // destructor
+   
+   fColumns.Delete();
+   if (fColInfos!=0) {
+      fColInfos->Delete();
+      delete fColInfos;  
+   }
+}
 
-   TSQLStructure::TSQLStructure() :
-      TObject(),
-      fParent(0),
-      fType(0),
-      fPointer(0),
-      fValue(),
-      fArrayIndex(-1),
-      fRepeatCnt(0),
-      fChilds()
+//________________________________________________________________________
+void TSQLTableData::AddColumn(const char* name, Long64_t value)
+{
+   // Add INT column to list of columns
+
+   TObjString* v = new TObjString(Form("%lld",value));
+   v->SetBit(BIT(20), kTRUE);
+   fColumns.Add(v);
+
+//   TSQLColumnData* col = new TSQLColumnData(name, value);
+//   fColumns.Add(col);
+   
+   if (fColInfos!=0)
+     fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), "INT"));
+}
+
+//________________________________________________________________________
+void TSQLTableData::AddColumn(const char* name, 
+                              const char* sqltype, 
+                              const char* value, 
+                              Bool_t numeric)
+{
+   // Add nomral column to list of columns
+
+   TObjString* v = new TObjString(value);
+   v->SetBit(BIT(20), numeric);
+   fColumns.Add(v);
+   
+//   TSQLColumnData* col = new TSQLColumnData(name, sqltype, value, numeric);
+//   fColumns.Add(col);
+
+   if (fColInfos!=0)
+     fColInfos->Add(new TSQLClassColumnInfo(name, DefineSQLName(name), sqltype));
+}
+
+//________________________________________________________________________
+TString TSQLTableData::DefineSQLName(const char* fullname)
+{
+   // produce suitable name for column, taking into account length limitation
+   
+   Int_t maxlen = fFile->SQLMaxIdentifierLength();
+   
+   Int_t len = strlen(fullname);
+   
+   if ((len<=maxlen) && !HasSQLName(fullname)) return TString(fullname);
+   
+   Int_t cnt = -1;
+   TString res, scnt;
+   
+   do {
+      
+      scnt.Form("%d",cnt);
+      Int_t numlen = cnt<0 ? 0 : scnt.Length();
+      
+      res = fullname;
+      
+      if (len + numlen > maxlen) 
+         res.Resize(maxlen - numlen);
+      
+      if (cnt>=0) res+=scnt;
+      
+      if (!HasSQLName(res.Data())) return res;
+      
+      cnt++;
+      
+   } while (cnt<10000);
+   
+   Error("DefineSQLName","Cannot find reasonable column name for field %s",fullname);
+   
+   return TString(fullname);
+}
+
+//________________________________________________________________________
+Bool_t TSQLTableData::HasSQLName(const char* sqlname)
+{
+   // checks if columns list already has that sql name
+   
+   TIter next(fColInfos);
+
+   TSQLClassColumnInfo* col = 0;
+   
+   while ((col = (TSQLClassColumnInfo*) next()) != 0) {
+      const char* colname = col->GetSQLName();
+      if (strcmp(colname, sqlname)==0) return kTRUE;
+   }
+   
+   return kFALSE;
+
+}
+
+//________________________________________________________________________
+Int_t TSQLTableData::GetNumColumns()
+{
+   // returns number of columns in provided set
+   
+   return fColumns.GetLast() +1;
+}
+
+//________________________________________________________________________
+const char* TSQLTableData::GetColumn(Int_t n)
+{
+   // returm column value
+   return fColumns[n]->GetName();
+}
+
+//________________________________________________________________________
+Bool_t TSQLTableData::IsNumeric(Int_t n)
+{
+   // identifies if column has numeric value
+   
+   return fColumns[n]->TestBit(BIT(20));
+}
+
+//________________________________________________________________________
+TObjArray* TSQLTableData::TakeColInfos() 
+{ 
+   // take ownership over colinfos
+   
+   TObjArray* res = fColInfos; 
+   fColInfos = 0; 
+   return res; 
+}
+
+//________________________________________________________________________
+
+ClassImp(TSQLStructure);
+
+TSQLStructure::TSQLStructure() :
+   TObject(),
+   fParent(0),
+   fType(0),
+   fPointer(0),
+   fValue(),
+   fArrayIndex(-1),
+   fRepeatCnt(0),
+   fChilds()
 {
    // default constructor
 }
@@ -608,23 +770,6 @@ void TSQLStructure::PrintLevel(Int_t level) const
       GetChild(n)->PrintLevel(level+2);
 }
 
-//________________________________________________________________________
-void TSQLStructure::AddCmd(TObjArray* cmds,
-                           const char* name, const char* value,
-                           const char* topname, const char* ns)
-{
-   // Add SQL command for raw table
-
-   if ((topname!=0) && (ns!=0)) {
-      TString buf;
-      buf+=topname;
-      buf+=ns;
-      buf+=name;
-      cmds->Add(new TNamed(buf.Data(), value));
-   } else
-      cmds->Add(new TNamed(name, value));
-}
-
 //________________________________________________________________________
 Bool_t TSQLStructure::IsNumericType(Int_t typ)
 {
@@ -678,13 +823,18 @@ const char* TSQLStructure::GetSimpleTypeName(Int_t typ)
    return 0;
 }
 
-// ======================================================================
+//___________________________________________________________
+
+// TSqlCmdsBuffer used as buffer for data, which are correspond to
+// particular class, defined by TSQLClassInfo instance
+// Support both TSQLStatement and Query modes
 
 class TSqlCmdsBuffer : public TObject {
 
 public:
-   TSqlCmdsBuffer(TSQLClassInfo* info = 0) :
+   TSqlCmdsBuffer(TSQLFile* f, TSQLClassInfo* info) :
       TObject(),
+      fFile(f),
       fInfo(info),
       fBlobStmt(0),
       fNormStmt(0)
@@ -695,8 +845,8 @@ public:
    {
       fNormCmds.Delete();
       fBlobCmds.Delete();
-      if (fBlobStmt!=0) delete fBlobStmt;
-      if (fNormStmt!=0) delete fNormStmt;
+      fFile->SQLDeleteStatement(fBlobStmt);
+      fFile->SQLDeleteStatement(fNormStmt);
    }
 
    void AddValues(Bool_t isnorm, const char* values)
@@ -706,6 +856,7 @@ public:
       else fBlobCmds.Add(str);
    }
 
+   TSQLFile* fFile;
    TSQLClassInfo* fInfo;
    TObjArray fNormCmds;
    TObjArray fBlobCmds;
@@ -713,9 +864,10 @@ public:
    TSQLStatement* fNormStmt;
 };
 
-
-
 //________________________________________________________________________
+// TSqlRegistry keeps data, used when object data transformed to sql query or
+// statements 
+
 class TSqlRegistry : public TObject {
 
 public:
@@ -759,7 +911,7 @@ public:
       fPool.DeleteValues();
       fLongStrValues.Delete();
       fRegValues.Delete();
-      if (fRegStmt) delete fRegStmt;
+      f->SQLDeleteStatement(fRegStmt);
    }
 
    Long64_t GetNextObjId() { return ++fLastObjId; }
@@ -776,7 +928,7 @@ public:
       if (sqlinfo==0) return 0;
       TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
       if (buf==0) {
-         buf = new TSqlCmdsBuffer(sqlinfo);
+         buf = new TSqlCmdsBuffer(f, sqlinfo);
          fPool.Add(sqlinfo, buf);
       }
       return buf;
@@ -827,6 +979,8 @@ public:
          TSqlCmdsBuffer* buf = (TSqlCmdsBuffer*) fPool.GetValue(sqlinfo);
          if (buf==0) continue;
          ConvertSqlValues(buf->fNormCmds, sqlinfo->GetClassTableName());
+         // ensure that raw table will be created
+         if (buf->fBlobCmds.GetLast()>=0) f->CreateRawTable(sqlinfo);
          ConvertSqlValues(buf->fBlobCmds, sqlinfo->GetRawTableName());
          if (buf->fBlobStmt)
             buf->fBlobStmt->Process();
@@ -848,24 +1002,25 @@ public:
          return;
       }
       
-      if (f->IsOracle()) {
-         if (fRegStmt==0) {
+      if (f->IsOracle() || f->IsODBC()) {
+         if ((fRegStmt==0) && f->SQLCanStatement()) {
             const char* quote = f->SQLIdentifierQuote();
-            TString sqlcmd;  
-            sqlcmd.Form("INSERT INTO %s%s%s VALUES (:1, :2, :3, :4)", 
-                     quote, sqlio::ObjectsTable, quote);
-            fRegStmt = f->fSQL->Statement(sqlcmd.Data(), 1000);
-            f->fQuerisCounter++;
+            
+            TString sqlcmd;
+            const char* pars = f->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
+            sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", 
+                     quote, sqlio::ObjectsTable, quote, pars);
+            fRegStmt = f->SQLStatement(sqlcmd.Data(), 1000);
          }
          
-         fRegStmt->NextIteration();
-         
-         fRegStmt->SetLong64(0, fKeyId);
-         fRegStmt->SetLong64(1, objid);
-         fRegStmt->SetString(2, cl->GetName());
-         fRegStmt->SetInt(3, cl->GetClassVersion());
-         
-         return;   
+         if (fRegStmt!=0) {
+            fRegStmt->NextIteration();
+            fRegStmt->SetLong64(0, fKeyId);
+            fRegStmt->SetLong64(1, objid);
+            fRegStmt->SetString(2, cl->GetName(), f->SQLSmallTextTypeLimit());
+            fRegStmt->SetInt(3, cl->GetClassVersion());
+            return;
+         }
       }      
       
       const char* valuequote = f->SQLValueQuote();
@@ -895,123 +1050,68 @@ public:
 
       return strid;
    }
-   
-   void ConvertBlobsOracle(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid)
-   {
-      TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
-      if (buf==0) return;
-      
-      TSQLStatement* stmt = buf->fBlobStmt;
-      if (stmt==0) {
-         const char* quote = f->SQLIdentifierQuote();
-         TString sqlcmd;
-         sqlcmd.Form("INSERT INTO %s%s%s VALUES (:1, :2, :3, :4)", 
-                     quote, sqlinfo->GetRawTableName(), quote);
-         stmt = f->fSQL->Statement(sqlcmd.Data(), 2000);
-         f->fQuerisCounter++;
-         buf->fBlobStmt = stmt;
-      }
 
-      TIter iter(blobs);
-      TNamed* cmd = 0;
-      
-      while ((cmd = (TNamed*)iter())!=0) {
-         stmt->NextIteration();
-          
-         stmt->SetLong64(0, fCurrentObjId);
-         stmt->SetInt(1, rawid);
-         stmt->SetString(2, cmd->GetName());
-         stmt->SetString(3, cmd->GetTitle());
-         
-         rawid++; 
-      }
-   }
-
-   void InsertToNormalTableOracle(TObjArray* columns, TSQLClassInfo* sqlinfo)
+   Bool_t InsertToNormalTableOracle(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
    {
       TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
-      if (buf==0) return;
+      if (buf==0) return kFALSE;
       
       TSQLStatement* stmt = buf->fNormStmt;
       if (stmt==0) {
+         // if one cannot create statement, do it normal way
+         if (!f->SQLCanStatement()) return kFALSE;
+         
          const char* quote = f->SQLIdentifierQuote();
          TString sqlcmd;
-         sqlcmd.Form("INSERT INTO %s%s%s VALUES (:", 
+         sqlcmd.Form("INSERT INTO %s%s%s VALUES (", 
                      quote, sqlinfo->GetClassTableName(), quote);
-         for (int n=0;n<=columns->GetLast();n++) {
-            if (n>0) sqlcmd +=", :";
-            sqlcmd += (n+1);
+         for (int n=0;n<columns->GetNumColumns();n++) {
+            if (n>0) sqlcmd +=", ";
+            if (f->IsOracle()) {
+               sqlcmd += ":"; 
+               sqlcmd += (n+1);
+            } else
+               sqlcmd += "?";
          }
          sqlcmd += ")";
                      
-         stmt = f->fSQL->Statement(sqlcmd.Data(), 1000);
-         f->fQuerisCounter++;
+         stmt = f->SQLStatement(sqlcmd.Data(), 1000);
+         if (stmt==0) return kFALSE;
          buf->fNormStmt = stmt;
       }
       
       stmt->NextIteration(); 
+      
+      Int_t sizelimit = f->SQLSmallTextTypeLimit();
        
-      TIter iter(columns);
-      TSQLColumnData* col;
-      Int_t ncol = 0;
-      while ((col=(TSQLColumnData*)iter())!=0) {
-         const char* value = col->GetValue();
-         stmt->SetString(ncol, value);
-         ncol++; 
-      }
-   }
-
-   void ConvertBlobs(TObjArray* blobs, TSQLClassInfo* sqlinfo, Int_t& rawid)
-   {
-
-      if (f->IsOracle()) {
-         ConvertBlobsOracle(blobs, sqlinfo, rawid);
-         return;
-      }
-       
-      TSqlCmdsBuffer* buf = GetCmdsBuffer(sqlinfo);
-      if (buf==0) return; 
-       
-      TString value, onecmd, cmdmask;
-
-      const char* valuequote = f->SQLValueQuote();
-
-      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();
-         TSQLStructure::AddStrBrackets(value, valuequote);
-         onecmd.Form(cmdmask.Data(), rawid++, cmd->GetName(), value.Data());
-         buf->AddValues(kFALSE, onecmd.Data());
+      for (Int_t ncol=0;ncol<columns->GetNumColumns();ncol++) {
+         const char* value = columns->GetColumn(ncol);
+         if (value==0) value = "";
+         stmt->SetString(ncol, value, sizelimit);
       }
+      
+      return kTRUE;
    }
 
-   void InsertToNormalTable(TObjArray* columns, TSQLClassInfo* sqlinfo)
+   void InsertToNormalTable(TSQLTableData* columns, TSQLClassInfo* sqlinfo)
    {
       // produce SQL query to insert object data into normal table
 
-      if (f->IsOracle()) {
-         InsertToNormalTableOracle(columns, sqlinfo);
-         return;
-      }
+      if (f->IsOracle() || f->IsODBC())
+         if (InsertToNormalTableOracle(columns, sqlinfo))
+           return;
 
-      TIter iter(columns);
-      TSQLColumnData* col;
       const char* valuequote = f->SQLValueQuote();
 
       TString values;
       
-      Bool_t first = kTRUE;
-
-      while ((col=(TSQLColumnData*)iter())!=0) {
-         if (first) first = kFALSE; 
-               else values+=", "; 
-         if (col->IsNumeric())
-            values+=col->GetValue();
+      for (Int_t n=0;n<columns->GetNumColumns();n++) {
+         if (n>0) values+=", "; 
+         
+         if (columns->IsNumeric(n))
+            values+=columns->GetColumn(n);
          else {
-            TString value = col->GetValue();
+            TString value = columns->GetColumn(n);
             TSQLStructure::AddStrBrackets(value, valuequote);
             values += value;
          }
@@ -1022,6 +1122,113 @@ public:
    }
 };
 
+
+//_____________________________________________________________________________
+
+// TSqlRawBuffer is used to convert raw data, which corresponds to one
+// object and belong to single SQL tables. Supoorts both statements 
+// and query mode
+
+class TSqlRawBuffer : public TObject {
+
+public:
+
+   TSqlRawBuffer(TSqlRegistry* reg, TSQLClassInfo* sqlinfo) :
+      TObject(),
+      fFile(0),
+      fInfo(0),
+      fCmdBuf(0),
+      fObjId(0),
+      fRawId(0),
+      fValueMask(),
+      fValueQuote(0),
+      fMaxStrSize(255)
+   {
+      fFile = reg->f;
+      fInfo = sqlinfo;
+      fCmdBuf = reg->GetCmdsBuffer(sqlinfo);
+      fObjId = reg->fCurrentObjId;
+      fValueQuote = fFile->SQLValueQuote();
+      fValueMask.Form("%lld, %s, %s%s%s, %s", fObjId, "%d", fValueQuote, "%s", fValueQuote, "%s");      
+      fMaxStrSize = reg->f->SQLSmallTextTypeLimit();
+   }
+   
+   virtual ~TSqlRawBuffer() 
+   {
+      // close blob statement for Oracle
+      TSQLStatement* stmt = fCmdBuf->fBlobStmt;
+      if ((stmt!=0) && fFile->IsOracle()) {
+         stmt->Process();
+         delete stmt;
+         fCmdBuf->fBlobStmt = 0;
+      }
+   }
+   
+   Bool_t IsAnyData() const { return fRawId>0; }
+
+   void AddLine(const char* name, const char* value, const char* topname = 0, const char* ns = 0)
+   {
+      if (fCmdBuf==0) return;
+      
+      // when first line is created, check all problems
+      if (fRawId==0) {
+         Bool_t maketmt = kFALSE;
+         if (fFile->IsOracle() || fFile->IsODBC())
+            maketmt = (fCmdBuf->fBlobStmt==0) && fFile->SQLCanStatement();
+            
+         if (maketmt) {
+            // ensure that raw table is exists
+            fFile->CreateRawTable(fInfo);
+            
+            const char* quote = fFile->SQLIdentifierQuote();
+            TString sqlcmd;
+            const char* params = fFile->IsOracle() ? ":1, :2, :3, :4" : "?, ?, ?, ?";
+            sqlcmd.Form("INSERT INTO %s%s%s VALUES (%s)", 
+                        quote, fInfo->GetRawTableName(), quote, params);
+            TSQLStatement* stmt = fFile->SQLStatement(sqlcmd.Data(), 2000);
+            fCmdBuf->fBlobStmt = stmt;
+         }
+      }
+      
+      TString buf;
+      const char* fullname = name;
+      if ((topname!=0) && (ns!=0)) {
+         buf+=topname;
+         buf+=ns;
+         buf+=name;
+         fullname = buf.Data();
+      }
+      
+      TSQLStatement* stmt = fCmdBuf->fBlobStmt;
+      
+      if (stmt!=0) {
+         stmt->NextIteration();
+         stmt->SetLong64(0, fObjId);
+         stmt->SetInt(1, fRawId++);
+         stmt->SetString(2, fullname, fMaxStrSize);
+//         Info("AddLine","name = %s value = %s",fullname, value);
+         stmt->SetString(3, value, fMaxStrSize);
+      } else {
+         TString valuebuf(value);
+         TSQLStructure::AddStrBrackets(valuebuf, fValueQuote);
+         TString cmd;
+         cmd.Form(fValueMask.Data(), fRawId++, fullname, valuebuf.Data());
+         fCmdBuf->AddValues(kFALSE, cmd.Data());         
+      }
+   }
+      
+   TSQLFile*  fFile;
+   TSQLClassInfo* fInfo;
+   TSqlCmdsBuffer* fCmdBuf;
+   Long64_t fObjId; 
+   Int_t fRawId;
+   TString fValueMask;
+   const char* fValueQuote;
+   TSQLStatement* fStmt;
+   Bool_t fUseStmt;
+   Int_t fMaxStrSize;
+};
+
 //________________________________________________________________________
 Long64_t TSQLStructure::FindMaxObjectId()
 {
@@ -1066,7 +1273,7 @@ Bool_t TSQLStructure::ConvertToTables(TSQLFile* file, Long64_t keyid, TObjArray*
 }
 
 //________________________________________________________________________
-void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const char* topname, Bool_t useblob)
+void TSQLStructure::PerformConversion(TSqlRegistry* reg, TSqlRawBuffer* blobs, const char* topname, Bool_t useblob)
 {
    // perform conversion of structure to sql statements
    // first tries convert it to normal form
@@ -1080,13 +1287,13 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const
 
       if (!StoreObject(reg, DefineObjectId(kFALSE), GetObjectClass())) break;
 
-      AddCmd(blobs, sqlio::ObjectRef, GetValue(), topname, ns);
+      blobs->AddLine(sqlio::ObjectRef, GetValue(), topname, ns);
 
       break;
    }
 
    case kSqlPointer: {
-      AddCmd(blobs, sqlio::ObjectPtr, fValue.Data(), topname,ns);
+      blobs->AddLine(sqlio::ObjectPtr, fValue.Data(), topname,ns);
       break;
    }
 
@@ -1095,7 +1302,7 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const
          topname = ((TClass*) fPointer)->GetName();
       else
          Error("PerformConversion","version without class");
-      AddCmd(blobs, sqlio::Version, fValue.Data(), topname, ns);
+      blobs->AddLine(sqlio::Version, fValue.Data(), topname, ns);
       break;
    }
 
@@ -1114,7 +1321,7 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const
          TString sobjid;
          sobjid.Form("%lld",objid);
          if (!StoreObject(reg, objid, info->GetClass(), kTRUE)) return;
-         AddCmd(blobs, sqlio::ObjectInst, sobjid.Data(), topname, ns);
+         blobs->AddLine(sqlio::ObjectInst, sobjid.Data(), topname, ns);
       }
       break;
    }
@@ -1155,14 +1362,14 @@ void TSQLStructure::PerformConversion(TSqlRegistry* reg, TObjArray* blobs, const
          }
       }
 
-      AddCmd(blobs, sbuf.Data(), value, (fArrayIndex>=0) ? 0 : topname, ns);
+      blobs->AddLine(sbuf.Data(), value, (fArrayIndex>=0) ? 0 : topname, ns);
 
       break;
    }
 
    case kSqlArray: {
       if (fValue.Length()>0)
-         AddCmd(blobs, sqlio::Array, fValue.Data(), topname, ns);
+         blobs->AddLine(sqlio::Array, fValue.Data(), topname, ns);
       for(Int_t n=0;n<=fChilds.GetLast();n++) {
          TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
          child->PerformConversion(reg, blobs, topname, useblob);
@@ -1187,8 +1394,6 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl,
          if (GetElement()) cout << "Element = " << GetElement()->GetName() << endl;
    }
 
-   TSQLClassInfo* sqlinfo = 0;
-
    Long64_t oldid = reg->fCurrentObjId;
    TClass* oldcl = reg->fCurrentObjClass;
 
@@ -1218,24 +1423,17 @@ Bool_t TSQLStructure::StoreObject(TSqlRegistry* reg, Long64_t objid, TClass* cl,
 
    if (!normstore) {
 
-      TObjArray objblobs;
+      // This is a case, when only raw table is exists
+
+      TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl);
+      TSqlRawBuffer rawdata(reg, sqlinfo);
 
-      // 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()*/);
-      }
-
-      if (objblobs.GetLast()<0)
-         res = kFALSE;
-      else {
-         sqlinfo = reg->f->RequestSQLClassInfo(cl);
-         reg->f->SyncSQLClassInfo(sqlinfo, 0, kTRUE);
-         Int_t currrawid = 0;
-         reg->ConvertBlobs(&objblobs, sqlinfo, currrawid);
+         child->PerformConversion(reg, &rawdata, 0 /*cl->GetName()*/);
       }
 
-      objblobs.Delete();
+      res = rawdata.IsAnyData();
    }
 
    if (registerobj)
@@ -1277,13 +1475,15 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg)
 
    TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(cl->GetName(), version);
 
-   TObjArray columns;
+   TSQLTableData columns(reg->f, sqlinfo);
    Bool_t needblob = kFALSE;
 
-   Int_t currrawid = 0;
+   TSqlRawBuffer rawdata(reg, sqlinfo);
+
+//   Int_t currrawid = 0;
 
    // add first column with object id
-   columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId));
+   columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
 
    for(Int_t n=0;n<=fChilds.GetLast();n++) {
       TSQLStructure* child = (TSQLStructure*) fChilds.At(n);
@@ -1302,39 +1502,39 @@ Bool_t TSQLStructure::StoreClassInNormalForm(TSqlRegistry* reg)
          continue;
       }
 
-      TObjArray blobs;
 
       Bool_t doblobs = kTRUE;
 
+      Int_t blobid = rawdata.fRawId; // keep id of first raw, used in class table 
+
       if (columntyp==kColObjectArray)
-         if (child->TryConvertObjectArray(reg, &blobs))
+         if (child->TryConvertObjectArray(reg, &rawdata))
             doblobs = kFALSE;
 
       if (doblobs)
-         child->PerformConversion(reg, &blobs, elem->GetName(), kFALSE);
-
-      Int_t blobid = -1;
-      if (blobs.GetLast()>=0) {
-         reg->f->SyncSQLClassInfoRawTables(sqlinfo, kTRUE);
-         blobid = currrawid; // column will contain first raw id
-         reg->ConvertBlobs(&blobs, sqlinfo, currrawid);
+         child->PerformConversion(reg, &rawdata, elem->GetName(), kFALSE);
+
+      if (blobid==rawdata.fRawId) 
+         blobid = -1; // no data for blob was created
+      else { 
+         //reg->f->CreateRawTable(sqlinfo);
+         //blobid = currrawid; // column will contain first raw id
+         //reg->ConvertBlobs(&blobs, sqlinfo, currrawid);
          needblob = kTRUE;
       }
-      blobs.Delete();
+      //blobs.Delete();
 
       TString blobname = elem->GetName();
       if (reg->f->GetUseSuffixes())
          blobname += sqlio::RawSuffix;
 
-      columns.Add(new TSQLColumnData(blobname, blobid));
+      columns.AddColumn(blobname, blobid);
    }
 
-   reg->f->SyncSQLClassInfo(sqlinfo, &columns, needblob);
+   reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
 
    reg->InsertToNormalTable(&columns, sqlinfo);
 
-   columns.Delete();
-
    return kTRUE;
 }
 
@@ -1357,7 +1557,7 @@ TString TSQLStructure::MakeArrayIndex(TStreamerElement* elem, Int_t index)
 }
 
 //________________________________________________________________________
-Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* columns)
+Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TSQLTableData* columns)
 {
    // tries to store element data in column
 
@@ -1386,11 +1586,11 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
       const char* stype = reg->f->SQLSmallTextType();
 
       if (len<=sizelimit)
-         columns->Add(new TSQLColumnData(colname.Data(), stype, value, kFALSE));
+         columns->AddColumn(colname.Data(), stype, value, kFALSE);
       else {
          Int_t strid = reg->AddLongString(value);
          TString buf = reg->f->CodeLongString(reg->fCurrentObjId, strid);
-         columns->Add(new TSQLColumnData(colname.Data(), stype, buf.Data(), kFALSE));
+         columns->AddColumn(colname.Data(), stype, buf.Data(), kFALSE);
       }
 
       return kTRUE;
@@ -1402,7 +1602,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
       Int_t resversion = basecl->GetClassVersion();
       if (!StoreObject(reg, objid, basecl, kFALSE))
          resversion = -1;
-      columns->Add(new TSQLColumnData(colname.Data(), resversion));
+      columns->AddColumn(colname.Data(), resversion);
       return kTRUE;
    }
 
@@ -1431,7 +1631,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
             objid = -1;  // this is a case, when no data was stored for this object
       }
 
-      columns->Add(new TSQLColumnData(colname.Data(), objid));
+      columns->AddColumn(colname.Data(), objid);
       return kTRUE;
    }
 
@@ -1461,11 +1661,12 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
          return kFALSE;
       }
 
-      columns->Add(new TSQLColumnData(colname.Data(), objid));
+      columns->AddColumn(colname.Data(), objid);
       return kTRUE;
    }
 
    if (columntyp==kColNormObjectArray) {
+       
       if (elem->GetArrayLength()!=NumChilds()) return kFALSE;
 
       for (Int_t index=0;index<NumChilds();index++) {
@@ -1474,18 +1675,16 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
              (child->GetType()!=kSqlObject)) return kFALSE;
          Bool_t normal = kTRUE;
 
-         Long64_t objid = -1;
+         Long64_t objid = child->DefineObjectId(kFALSE);
 
-         if (child->GetType()==kSqlObject) {
-            objid = child->DefineObjectId(kFALSE);
+         if (child->GetType()==kSqlObject)
             normal = child->StoreObject(reg, objid, child->GetObjectClass());
-         }
 
          if (!normal) return kFALSE;
 
          colname = DefineElementColumnName(elem, reg->f, index);
 
-         columns->Add(new TSQLColumnData(colname.Data(), objid));
+         columns->AddColumn(colname.Data(), objid);
       }
       return kTRUE;
    }
@@ -1505,7 +1704,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
 
       if (!normal) return kFALSE;
 
-      columns->Add(new TSQLColumnData(colname.Data(), objid));
+      columns->AddColumn(colname.Data(), objid);
       return kTRUE;
    }
 
@@ -1525,7 +1724,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
 
       const char* sqltype = reg->f->SQLCompatibleType(typ);
 
-      columns->Add(new TSQLColumnData(colname.Data(), sqltype, value, IsNumericType(typ)));
+      columns->AddColumn(colname.Data(), sqltype, value, IsNumericType(typ));
 
       return kTRUE;
    }
@@ -1553,7 +1752,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
 
          while (index<last) {
             colname = DefineElementColumnName(elem, reg->f, index);
-            columns->Add(new TSQLColumnData(colname.Data(), sqltype, value, kTRUE));
+            columns->AddColumn(colname.Data(), sqltype, value, kTRUE);
             index++;
          }
       }
@@ -1564,7 +1763,7 @@ Bool_t TSQLStructure::StoreElementInNormalForm(TSqlRegistry* reg, TObjArray* col
 }
 
 //________________________________________________________________________
-Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TObjArray* blobs)
+Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TSqlRawBuffer* blobs)
 {
    // tries to write array of objects as lis of object refereneces
    // in _streamer_ table, while objects itself will be stored in
@@ -1600,7 +1799,7 @@ Bool_t TSQLStructure::TryConvertObjectArray(TSqlRegistry* reg, TObjArray* blobs)
       TString sobjid;
       sobjid.Form("%lld", objid);
 
-      AddCmd(blobs, sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns);
+      blobs->AddLine(sqlio::ObjectRef_Arr, sobjid.Data(), elem->GetName(), ns);
    }
 
    return kTRUE;
@@ -1653,22 +1852,20 @@ Bool_t TSQLStructure::StoreTObject(TSqlRegistry* reg)
 
    if (sqlinfo==0) return kFALSE;
 
-   TObjArray columns;
+   TSQLTableData columns(reg->f, sqlinfo);
 
    const char* uinttype = reg->f->SQLCompatibleType(TStreamerInfo::kUInt);
 
-   columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId));
+   columns.AddColumn(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));
-   columns.Add(new TSQLColumnData(sqlio::TObjectProcessId, "CHAR(3)", (str_prid ? str_prid->GetValue() : ""), kFALSE));
+   columns.AddColumn(sqlio::TObjectUniqueId, uinttype, str_id->GetValue(), kTRUE);
+   columns.AddColumn(sqlio::TObjectBits, uinttype, str_bits->GetValue(), kTRUE);
+   columns.AddColumn(sqlio::TObjectProcessId, "CHAR(3)", (str_prid ? str_prid->GetValue() : ""), kFALSE);
 
-   reg->f->SyncSQLClassInfo(sqlinfo, &columns, kFALSE);
+   reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
 
    reg->InsertToNormalTable(&columns, sqlinfo);
 
-   columns.Delete();
-
    return kTRUE;
 }
 
@@ -1684,14 +1881,14 @@ Bool_t TSQLStructure::StoreTString(TSqlRegistry* reg)
    TSQLClassInfo* sqlinfo = reg->f->RequestSQLClassInfo(TString::Class());
    if (sqlinfo==0) return kFALSE;
 
-   TObjArray columns;
+   TSQLTableData columns(reg->f, sqlinfo);
 
-   columns.Add(new TSQLColumnData(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId));
-   columns.Add(new TSQLColumnData(sqlio::TStringValue, reg->f->SQLBigTextType(), value, kFALSE));
+   columns.AddColumn(reg->f->SQLObjectIdColumn(), reg->fCurrentObjId);
+   columns.AddColumn(sqlio::TStringValue, reg->f->SQLBigTextType(), value, kFALSE);
 
-   reg->f->SyncSQLClassInfo(sqlinfo, &columns, kFALSE);
+   reg->f->CreateClassTable(sqlinfo, columns.TakeColInfos());
+   
    reg->InsertToNormalTable(&columns, sqlinfo);
-   columns.Delete();
    return kTRUE;
 }
 
@@ -1966,7 +2163,7 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObje
          break;
       }
 
-      TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(clname, version);
+      TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname, version);
       if (sqlinfo==0) return kColUnknown;
 
       // this will indicate that streamer is completely custom
@@ -2011,7 +2208,7 @@ Int_t TSQLStructure::LocateElementColumn(TSQLFile* f, TBufferSQL2* buf, TSQLObje
          break;
       }
 
-      TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(clname.Data(), version);
+      TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(clname.Data(), version);
       if (sqlinfo==0) return kColUnknown;
 
       if (sqlinfo->IsClassTableExist()) {
@@ -2099,7 +2296,7 @@ Bool_t TSQLStructure::UnpackTObject(TSQLFile* f, TBufferSQL2* buf, TSQLObjectDat
 {
    // Unpack TObject data in form, understodable by custom TObject streamer
 
-   TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(TObject::Class()->GetName(), clversion);
+   TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TObject::Class()->GetName(), clversion);
    if (sqlinfo==0) return kFALSE;
 
    TSQLObjectData* tobjdata = buf->SqlObjectData(objid, sqlinfo);
@@ -2130,7 +2327,7 @@ Bool_t TSQLStructure::UnpackTString(TSQLFile* f, TBufferSQL2* buf, TSQLObjectDat
 {
    // Unpack TString data in form, understodable by custom TString streamer
 
-   TSQLClassInfo* sqlinfo = f->RequestSQLClassInfo(TString::Class()->GetName(), clversion);
+   TSQLClassInfo* sqlinfo = f->FindSQLClassInfo(TString::Class()->GetName(), clversion);
    if (sqlinfo==0) return kFALSE;
 
    TSQLObjectData* tstringdata = buf->SqlObjectData(objid, sqlinfo);
diff --git a/xml/inc/TKeyXML.h b/xml/inc/TKeyXML.h
index 4743f4373c246d290e41a009b1afd858db2370eb..8ac63e37e043fac58fe1ce0e9400348d56291b69 100644
--- a/xml/inc/TKeyXML.h
+++ b/xml/inc/TKeyXML.h
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TKeyXML.h,v 1.4 2006/01/25 16:00:11 pcanal Exp $
+// @(#)root/xml:$Name:  $:$Id: TKeyXML.h,v 1.5 2006/02/01 18:57:41 pcanal Exp $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -26,9 +26,9 @@ class TKeyXML : public TKey {
       TKeyXML();
     
    public:
-      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);
+      TKeyXML(TDirectory* mother, Long64_t keyid, const TObject* obj, const char* name = 0, const char* title = 0);
+      TKeyXML(TDirectory* mother, Long64_t keyid, const void* obj, const TClass* cl, const char* name, const char* title = 0);
+      TKeyXML(TDirectory* mother, Long64_t keyid, XMLNodePointer_t keynode);
       virtual ~TKeyXML();
 
       // redefined TKey Methods
@@ -55,15 +55,23 @@ class TKeyXML : public TKey {
       // TKeyXML specific methods
 
       XMLNodePointer_t  KeyNode() const { return fKeyNode; }
-
+      Long64_t          GetKeyId() const { return fKeyId; }
+      Bool_t            IsSubdir() const { return fSubdir; }
+      void              SetSubir() { fSubdir = kTRUE; }
+      void              UpdateObject(TObject* obj);
+      void              UpdateAttributes();
+      
    protected:
       virtual Int_t     Read(const char *name) { return TKey::Read(name); }
       void              StoreObject(const void* obj, const TClass* cl);
+      void              StoreKeyAttributes();
       TXMLEngine*       XMLEngine();
       
       void*             XmlReadAny(void* obj, const TClass* expectedClass);
       
-      XMLNodePointer_t  fKeyNode;  //!
+      XMLNodePointer_t  fKeyNode;  //! node with stored object
+      Long64_t          fKeyId;    //! unique identifier of key for search methods
+      Bool_t            fSubdir;   //! indicates that key contains subdirectory
 
    ClassDef(TKeyXML,1) // a special TKey for XML files      
 };
diff --git a/xml/inc/TXMLEngine.h b/xml/inc/TXMLEngine.h
index 16b59a2419a17b4f270c026184fea3a8b3e6478b..996050e3af7aa7a3bd1a3497f9bbff842e4da6d6 100644
--- a/xml/inc/TXMLEngine.h
+++ b/xml/inc/TXMLEngine.h
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLEngine.h,v 1.10 2006/01/20 01:12:13 pcanal Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLEngine.h,v 1.11 2006/05/30 12:59:30 brun Exp $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -37,6 +37,7 @@ class TXMLEngine : public TObject {
                                 const char* name, const char* value);
       XMLAttrPointer_t  NewIntAttr(XMLNodePointer_t xmlnode, const char* name, Int_t value);
       void              FreeAttr(XMLNodePointer_t xmlnode, const char* name);
+      void              FreeAllAttr(XMLNodePointer_t xmlnode);
       XMLAttrPointer_t  GetFirstAttr(XMLNodePointer_t xmlnode);
       XMLAttrPointer_t  GetNextAttr(XMLAttrPointer_t xmlattr);
       const char*       GetAttrName(XMLAttrPointer_t xmlattr);
@@ -48,6 +49,7 @@ class TXMLEngine : public TObject {
       const char*       GetNSName(XMLNsPointer_t ns);
       const char*       GetNSReference(XMLNsPointer_t ns);
       void              AddChild(XMLNodePointer_t parent, XMLNodePointer_t child);
+      void              AddChildFirst(XMLNodePointer_t parent, XMLNodePointer_t child);
       void              UnlinkNode(XMLNodePointer_t node);
       void              FreeNode(XMLNodePointer_t xmlnode);
       void              UnlinkFreeNode(XMLNodePointer_t xmlnode);
diff --git a/xml/inc/TXMLFile.h b/xml/inc/TXMLFile.h
index a1582abfec3024e7d3bbf3008509f8128dc996c3..8f97e6652aefd1a9b5dbce9c2b8be0a3ceb0f9e7 100644
--- a/xml/inc/TXMLFile.h
+++ b/xml/inc/TXMLFile.h
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLFile.h,v 1.12 2006/01/20 01:12:13 pcanal Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLFile.h,v 1.13 2006/02/01 18:57:41 pcanal Exp $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -30,101 +30,115 @@ class TStreamerInfo;
 
 
 class TXMLFile : public TFile, public TXMLSetup {
-   protected:
-      void             InitXmlFile(Bool_t create);
-      // Interface to basic system I/O routines
-      virtual Int_t    SysOpen(const char*, Int_t, UInt_t) { return 0; }
-      virtual Int_t    SysClose(Int_t) { return 0; }
-      virtual Int_t    SysRead(Int_t, void*, Int_t) { return 0; }
-      virtual Int_t    SysWrite(Int_t, const void*, Int_t) { return 0; }
-      virtual Long64_t SysSeek(Int_t, Long64_t, Int_t) { return 0; }
-      virtual Int_t    SysStat(Int_t, Long_t*, Long64_t*, Long_t*, Long_t*) { return 0; }
-      virtual Int_t    SysSync(Int_t) { return 0; }
-
-   private:
-      //let the compiler do the job. gcc complains when the following line is activated
-      //TXMLFile(const TXMLFile &) {}            //Files cannot be copied
-      void operator=(const TXMLFile &);
-
-   public:
-      TXMLFile();
-      TXMLFile(const char* filename, Option_t* option = "read", const char* title = "title", Int_t compression = 1);
-      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() {}
-
-      virtual Long64_t  GetEND() const { return 0; }
-      virtual Int_t     GetErrno() const { return 0; }
-      virtual void      ResetErrno() const {}
-
-      virtual Int_t     GetNfree() const { return 0; }
-      virtual Int_t     GetNbytesInfo() const {return 0; }
-      virtual Int_t     GetNbytesFree() const {return 0; }
-      virtual Long64_t  GetSeekFree() const {return 0; }
-      virtual Long64_t  GetSeekInfo() const {return 0; }
-      virtual Long64_t  GetSize() const { return 0; }
-      virtual TList*    GetStreamerInfoList();
-      Int_t             GetIOVersion() const { return fIOVersion; }          
-
-      virtual Bool_t    IsOpen() const;
-
-      virtual void      MakeFree(Long64_t, Long64_t) {}
-      virtual void      MakeProject(const char *, const char* ="*", Option_t* ="new") {} // *MENU*
-      virtual void      Map() {} // 
-      virtual void      Paint(Option_t* ="") {}
-      virtual void      Print(Option_t* ="") const {}
-      virtual Bool_t    ReadBuffer(char*, Int_t) { return kFALSE; }
-      virtual void      ReadFree() {}
-      virtual Int_t     Recover() { return 0; }
-      virtual Int_t     ReOpen(Option_t *mode);
-      virtual void      Seek(Long64_t, ERelativeTo=kBeg) {}
-
-      virtual void      SetEND(Long64_t) {}
-      virtual Int_t     Sizeof() const { return 0; }
-
-      virtual void      UseCache(Int_t = 10, Int_t = TCache::kDfltPageSize) {}
-      virtual Bool_t    WriteBuffer(const char*, Int_t) { return kFALSE; }
-      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      WriteStreamerInfo();
-
-      // XML specific functions
-      
-      virtual void      SetXmlLayout(EXMLLayout layout);
-      virtual void      SetStoreStreamerInfos(Bool_t iConvert = kTRUE);
-      virtual void      SetUsedDtd(Bool_t use = kTRUE);
-      virtual void      SetUseNamespaces(Bool_t iUseNamespaces = kTRUE);
-
-      TXMLEngine*       XML() { return fXML; } 
-
-   protected:
-      // functions to store streamer infos
-      
-      void              StoreStreamerElement(XMLNodePointer_t node, TStreamerElement* elem);
-      void              ReadStreamerElement(XMLNodePointer_t node, TStreamerInfo* info);
-
-      Bool_t            ReadFromFile();
-
-      void              SaveToFile();
-
-      static void       ProduceFileNames(const char* filename, TString& fname, TString& dtdname);
-
-      XMLDocPointer_t   fDoc;                  //!
-
-      XMLNodePointer_t  fStreamerInfoNode;     //!  pointer of node with streamer info data
-      
-      TXMLEngine*       fXML;                  //! object for interface with xml library
-      
-      Int_t             fIOVersion;            //! indicates format of ROOT xml file
-      
-   ClassDef(TXMLFile, 2)  //ROOT file in XML format
+
+protected:
+
+   void             InitXmlFile(Bool_t create);
+   // Interface to basic system I/O routines
+   virtual Int_t    SysOpen(const char*, Int_t, UInt_t) { return 0; }
+   virtual Int_t    SysClose(Int_t) { return 0; }
+   virtual Int_t    SysRead(Int_t, void*, Int_t) { return 0; }
+   virtual Int_t    SysWrite(Int_t, const void*, Int_t) { return 0; }
+   virtual Long64_t SysSeek(Int_t, Long64_t, Int_t) { return 0; }
+   virtual Int_t    SysStat(Int_t, Long_t*, Long64_t*, Long_t*, Long_t*) { return 0; }
+   virtual Int_t    SysSync(Int_t) { return 0; }
+
+   // Overwrite methods for directory I/O
+   virtual Long64_t DirCreateEntry(TDirectory*);
+   virtual Int_t    DirReadKeys(TDirectory*);
+   virtual void     DirWriteKeys(TDirectory*);
+   virtual void     DirWriteHeader(TDirectory*);
+
+private:
+   //let the compiler do the job. gcc complains when the following line is activated
+   //TXMLFile(const TXMLFile &) {}            //Files cannot be copied
+   void operator=(const TXMLFile &);
+
+public:
+   TXMLFile();
+   TXMLFile(const char* filename, Option_t* option = "read", const char* title = "title", Int_t compression = 1);
+   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() {}
+
+   virtual Long64_t  GetEND() const { return 0; }
+   virtual Int_t     GetErrno() const { return 0; }
+   virtual void      ResetErrno() const {}
+
+   virtual Int_t     GetNfree() const { return 0; }
+   virtual Int_t     GetNbytesInfo() const {return 0; }
+   virtual Int_t     GetNbytesFree() const {return 0; }
+   virtual Long64_t  GetSeekFree() const {return 0; }
+   virtual Long64_t  GetSeekInfo() const {return 0; }
+   virtual Long64_t  GetSize() const { return 0; }
+   virtual TList*    GetStreamerInfoList();
+   Int_t             GetIOVersion() const { return fIOVersion; }          
+
+   virtual Bool_t    IsOpen() const;
+
+   virtual void      MakeFree(Long64_t, Long64_t) {}
+   virtual void      MakeProject(const char *, const char* ="*", Option_t* ="new") {} // *MENU*
+   virtual void      Map() {} // 
+   virtual void      Paint(Option_t* ="") {}
+   virtual void      Print(Option_t* ="") const {}
+   virtual Bool_t    ReadBuffer(char*, Int_t) { return kFALSE; }
+   virtual void      ReadFree() {}
+   virtual Int_t     Recover() { return 0; }
+   virtual Int_t     ReOpen(Option_t *mode);
+   virtual void      Seek(Long64_t, ERelativeTo=kBeg) {}
+
+   virtual void      SetEND(Long64_t) {}
+   virtual Int_t     Sizeof() const { return 0; }
+
+   virtual void      UseCache(Int_t = 10, Int_t = TCache::kDfltPageSize) {}
+   virtual Bool_t    WriteBuffer(const char*, Int_t) { return kFALSE; }
+   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      WriteStreamerInfo();
+
+   // XML specific functions
+   
+   virtual void      SetXmlLayout(EXMLLayout layout);
+   virtual void      SetStoreStreamerInfos(Bool_t iConvert = kTRUE);
+   virtual void      SetUsedDtd(Bool_t use = kTRUE);
+   virtual void      SetUseNamespaces(Bool_t iUseNamespaces = kTRUE);
+
+   TXMLEngine*       XML() { return fXML; } 
+
+protected:
+   // functions to store streamer infos
+   
+   void              StoreStreamerElement(XMLNodePointer_t node, TStreamerElement* elem);
+   void              ReadStreamerElement(XMLNodePointer_t node, TStreamerInfo* info);
+
+   Bool_t            ReadFromFile();
+   Int_t             ReadKeysList(TDirectory* dir, XMLNodePointer_t topnode);
+   TKeyXML*          FindDirKey(TDirectory* dir);
+   TDirectory*       FindKeyDir(TDirectory* mother, Long64_t keyid);
+   void              CombineNodesTree(TDirectory* dir, XMLNodePointer_t topnode, Bool_t dolink);
+
+   void              SaveToFile();
+
+   static void       ProduceFileNames(const char* filename, TString& fname, TString& dtdname);
+
+   XMLDocPointer_t   fDoc;                  //!
+
+   XMLNodePointer_t  fStreamerInfoNode;     //!  pointer of node with streamer info data
+   
+   TXMLEngine*       fXML;                  //! object for interface with xml library
+   
+   Int_t             fIOVersion;            //! indicates format of ROOT xml file
+   
+   Long64_t          fKeyCounter;           //! counter of created keys, used for keys id
+   
+ClassDef(TXMLFile, 2)  //ROOT file in XML format
 };
 
 
diff --git a/xml/src/TKeyXML.cxx b/xml/src/TKeyXML.cxx
index 0cd49c9350b2048648bd055861a3b3c59a260274..f126889c78231db9c8d471b199e48784930b2d27 100644
--- a/xml/src/TKeyXML.cxx
+++ b/xml/src/TKeyXML.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TKeyXML.cxx,v 1.6 2006/01/25 16:00:11 pcanal Exp $
+// @(#)root/xml:$Name:  $:$Id: TKeyXML.cxx,v 1.7 2006/02/01 18:57:41 pcanal Exp $
 // Author: Sergey Linev, Rene Brun  10.05.2004
 
 /*************************************************************************
@@ -30,15 +30,19 @@ ClassImp(TKeyXML);
 //______________________________________________________________________________
 TKeyXML::TKeyXML() :
    TKey(),
-   fKeyNode(0)
+   fKeyNode(0),
+   fKeyId(0),
+   fSubdir(kFALSE)
 {
    // default constructor
 }
 
 //______________________________________________________________________________
-TKeyXML::TKeyXML(TDirectory* mother, const TObject* obj, const char* name) :
+TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, const TObject* obj, const char* name, const char* title) :
     TKey(mother),
-    fKeyNode(0)
+    fKeyNode(0),
+    fKeyId(keyid),
+    fSubdir(kFALSE)
 {
    // Creates TKeyXML and convert obj data to xml structures
 
@@ -51,26 +55,50 @@ TKeyXML::TKeyXML(TDirectory* mother, const TObject* obj, const char* name) :
       } else
          SetName("Noname");
 
+   if (title) SetTitle(title);
+
+   fCycle  = GetMotherDir()->AppendKey(this);
+
+   TXMLEngine* xml = XMLEngine();
+   if (xml!=0)
+      fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0);
+
+   fDatime.Set();
+
    StoreObject((void*)obj, obj ? obj->IsA() : 0);
 }
 
 //______________________________________________________________________________
-TKeyXML::TKeyXML(TDirectory* mother, const void* obj, const TClass* cl, const char* name) :
+TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, const void* obj, const TClass* cl, const char* name, const char* title) :
    TKey(mother),
-   fKeyNode(0)
+   fKeyNode(0),
+   fKeyId(keyid),
+   fSubdir(kFALSE)
 {
    // Creates TKeyXML and convert obj data to xml structures
 
    if (name && *name) SetName(name);
    else SetName(cl ? cl->GetName() : "Noname");
 
+   if (title) SetTitle(title);
+
+   fCycle  = GetMotherDir()->AppendKey(this);
+
+   TXMLEngine* xml = XMLEngine();
+   if (xml!=0)
+      fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0);
+
+   fDatime.Set();
+
    StoreObject(obj, cl);
 }
 
 //______________________________________________________________________________
-TKeyXML::TKeyXML(TDirectory* mother, XMLNodePointer_t keynode) :
+TKeyXML::TKeyXML(TDirectory* mother, Long64_t keyid, XMLNodePointer_t keynode) :
    TKey(mother),
-   fKeyNode(keynode)
+   fKeyNode(keynode),
+   fKeyId(keyid),
+   fSubdir(kFALSE)
 {
    // Creates TKeyXML and takes ownership over xml node, from which object can be restored
 
@@ -119,17 +147,14 @@ void TKeyXML::Delete(Option_t * /*option*/)
 }
 
 //______________________________________________________________________________
-void TKeyXML::StoreObject(const void* obj, const TClass* cl)
+void TKeyXML::StoreKeyAttributes()
 {
-   //  convert object to xml structure and keep this structure in key
+   // Stores keys attributes in key node
    
-   TXMLFile* f = (TXMLFile*) GetFile();
    TXMLEngine* xml = XMLEngine();
-   if ((f==0) || (xml==0)) return;
-
-   fCycle  = GetMotherDir()->AppendKey(this);
+   TXMLFile* f = (TXMLFile*) GetFile();
+   if ((f==0) || (xml==0) || (fKeyNode==0)) return;
 
-   fKeyNode = xml->NewChild(0, 0, xmlio::Xmlkey, 0);
    xml->NewAttr(fKeyNode, 0, xmlio::Name, GetName());
    
    xml->NewIntAttr(fKeyNode, xmlio::Cycle, fCycle);
@@ -137,10 +162,21 @@ void TKeyXML::StoreObject(const void* obj, const TClass* cl)
    if (f->GetIOVersion()>1) {
       if (strlen(GetTitle())>0)
          xml->NewAttr(fKeyNode, 0, xmlio::Title, GetTitle());
-      fDatime.Set();
       xml->NewAttr(fKeyNode, 0, xmlio::CreateTm, fDatime.AsSQLString());
    }
+}
+
+//______________________________________________________________________________
+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) || (fKeyNode==0)) return;
+
+   StoreKeyAttributes();
+
    TBufferXML buffer(TBuffer::kWrite, f);
    if (f->GetIOVersion()==1)
       buffer.SetBit(TBuffer::kCannotHandleMemberWiseStreaming, kFALSE);
@@ -148,13 +184,49 @@ void TKeyXML::StoreObject(const void* obj, const TClass* cl)
    XMLNodePointer_t node = buffer.XmlWriteAny(obj, cl);
 
    if (node!=0)
-      xml->AddChild(fKeyNode, node);
-
+      xml->AddChildFirst(fKeyNode, node);
+      
    buffer.XmlWriteBlock(fKeyNode);
 
    if (cl) fClassName = cl->GetName();
 }
 
+//______________________________________________________________________________
+void TKeyXML::UpdateAttributes()
+{
+   // update key attributes in key node
+   
+   TXMLEngine* xml = XMLEngine();
+   if ((xml==0) || (fKeyNode==0)) return;
+
+   xml->FreeAllAttr(fKeyNode);
+   
+   StoreKeyAttributes();
+}
+
+//______________________________________________________________________________
+void TKeyXML::UpdateObject(TObject* obj)
+{
+   // updates object, stored in the node
+   // Used for TDirectory data update
+
+   TXMLFile* f = (TXMLFile*) GetFile();
+   TXMLEngine* xml = XMLEngine();
+   if ((f==0) || (xml==0) || (obj==0) || (fKeyNode==0)) return;
+   
+   XMLNodePointer_t objnode = xml->GetChild(fKeyNode);
+   xml->SkipEmpty(objnode);
+
+   if (objnode==0) return;
+
+   xml->UnlinkNode(objnode);
+   xml->FreeNode(objnode);
+   
+   xml->FreeAllAttr(fKeyNode);
+   
+   StoreObject(obj, obj->IsA());
+}
+
 //______________________________________________________________________________
 Int_t TKeyXML::Read(TObject* tobj)
 {
@@ -184,9 +256,12 @@ TObject* TKeyXML::ReadObj()
          TDirectory *dir = (TDirectory*) tobj;
          dir->SetName(GetName());
          dir->SetTitle(GetTitle());
-         dir->ReadKeys();
+         dir->SetSeekDir(GetKeyId());
+         // set mother before reading keys
          dir->SetMother(fMotherDir);
+         dir->ReadKeys();
          fMotherDir->Append(dir);
+         fSubdir = kTRUE;
       }
    }
        
diff --git a/xml/src/TXMLEngine.cxx b/xml/src/TXMLEngine.cxx
index 79eea149798d038b04f4addc38dcb8fb728c6f59..789aaeb52bd3b029a94fa062a004eef7315eec67 100644
--- a/xml/src/TXMLEngine.cxx
+++ b/xml/src/TXMLEngine.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLEngine.cxx,v 1.18 2006/05/09 10:24:27 brun Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLEngine.cxx,v 1.19 2006/05/30 12:59:30 brun Exp $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -475,6 +475,23 @@ void TXMLEngine::FreeAttr(XMLNodePointer_t xmlnode, const char* name)
    }
 }
 
+//______________________________________________________________________________
+void TXMLEngine::FreeAllAttr(XMLNodePointer_t xmlnode)
+{
+   // Free all attributes of the node
+   if (xmlnode==0) return;
+   
+   SXmlNode_t* node = (SXmlNode_t*) xmlnode;
+   SXmlAttr_t* attr = node->fAttr;
+   while (attr!=0) {
+      SXmlAttr_t* next = attr->fNext;
+      free(attr);
+      attr = next;
+   }
+   node->fAttr = 0;
+}
+
+
 //______________________________________________________________________________
 XMLAttrPointer_t TXMLEngine::GetFirstAttr(XMLNodePointer_t xmlnode)
 {
@@ -623,6 +640,23 @@ void TXMLEngine::AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
    }
 }
 
+//______________________________________________________________________________
+void TXMLEngine::AddChildFirst(XMLNodePointer_t parent, XMLNodePointer_t child)
+{
+   // add node as first child 
+   
+   if ((parent==0) || (child==0)) return;
+   SXmlNode_t* pnode = (SXmlNode_t*) parent;
+   SXmlNode_t* cnode = (SXmlNode_t*) child;
+   cnode->fParent = pnode;
+   
+   cnode->fNext = pnode->fChild;
+   pnode->fChild = cnode;
+   
+   if (pnode->fLastChild==0) pnode->fLastChild = cnode;
+}
+
+
 //______________________________________________________________________________
 void TXMLEngine::UnlinkNode(XMLNodePointer_t xmlnode)
 {
diff --git a/xml/src/TXMLFile.cxx b/xml/src/TXMLFile.cxx
index 6170f0fca048a5de033fbe26dfef53a8d7d8839f..fbc98ad22085b68df82e887657841b1631144f71 100644
--- a/xml/src/TXMLFile.cxx
+++ b/xml/src/TXMLFile.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Name:  $:$Id: TXMLFile.cxx,v 1.18 2006/02/01 18:57:41 pcanal Exp $
+// @(#)root/xml:$Name:  $:$Id: TXMLFile.cxx,v 1.19 2006/03/20 21:43:44 pcanal Exp $
 // Author: Sergey Linev, Rene Brun  10.05.2004
 
 /*************************************************************************
@@ -96,9 +96,12 @@ TXMLFile::TXMLFile() :
    TXMLSetup(),
    fDoc(0),
    fStreamerInfoNode(0),
-   fXML(0)
+   fXML(0),
+   fKeyCounter(0)
 {
    // default TXMLFile constructor
+   
+   SetBit(kBinaryFile, kFALSE);
 }
 
 
@@ -107,7 +110,9 @@ TXMLFile::TXMLFile(const char* filename, Option_t* option, const char* title, In
    TFile(),
    TXMLSetup(),
    fDoc(0),
-   fStreamerInfoNode(0)
+   fStreamerInfoNode(0),
+   fXML(0),
+   fKeyCounter(0)
 {
    // Open or creates local XML file with name filename.
    // It is recommended to specify filename as "<file>.xml". The suffix ".xml"
@@ -162,6 +167,7 @@ TXMLFile::TXMLFile(const char* filename, Option_t* option, const char* title, In
    fProcessIDs = 0;
    fNProcessIDs= 0;
    fIOVersion  = TXMLFile::Class_Version();
+   SetBit(kBinaryFile, kFALSE);
 
    fOption = option;
    fOption.ToUpper();
@@ -327,7 +333,6 @@ void TXMLFile::Close(Option_t *option)
       fClassIndex = 0;
    }
 
-
    if (fStreamerInfoNode) {
       fXML->FreeNode(fStreamerInfoNode);
       fStreamerInfoNode = 0;
@@ -436,7 +441,7 @@ TKey* TXMLFile::CreateKey(TDirectory* mother, const TObject* obj, const char* na
 {
    // create XML key, which will store object in xml structures
 
-   return new TKeyXML(mother, obj, name);
+   return new TKeyXML(mother, ++fKeyCounter, obj, name);
 }
 
 //______________________________________________________________________________
@@ -444,7 +449,7 @@ TKey* TXMLFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl,
 {
    // create XML key, which will store object in xml structures
 
-   return new TKeyXML(mother, obj, cl, name);
+   return new TKeyXML(mother, ++fKeyCounter, obj, cl, name);
 }
 
 //______________________________________________________________________________
@@ -517,11 +522,14 @@ void TXMLFile::SaveToFile()
    TString fname, dtdname;
    ProduceFileNames(fRealName, fname, dtdname);
 
+/*
    TIter iter(GetListOfKeys());
    TKeyXML* key = 0;
-
    while ((key=(TKeyXML*)iter()) !=0)
       fXML->AddChild(fRootNode, key->KeyNode());
+*/      
+
+   CombineNodesTree(this, fRootNode, kTRUE);
 
    WriteStreamerInfo();
 
@@ -532,14 +540,37 @@ void TXMLFile::SaveToFile()
 
    fXML->SaveDoc(fDoc, fname, layout);
 
-   iter.Reset();
+/*   iter.Reset();
    while ((key=(TKeyXML*)iter()) !=0)
       fXML->UnlinkNode(key->KeyNode());
+*/
+   CombineNodesTree(this, fRootNode, kFALSE);
 
    if (fStreamerInfoNode)
       fXML->UnlinkNode(fStreamerInfoNode);
 }
 
+//______________________________________________________________________________
+void TXMLFile::CombineNodesTree(TDirectory* dir, XMLNodePointer_t topnode, Bool_t dolink)
+{
+   // Connect/disconnect all file nodes to single tree before/after saving
+   
+   if (dir==0) return;
+   
+   TIter iter(dir->GetListOfKeys());
+   TKeyXML* key = 0;
+
+   while ((key=(TKeyXML*)iter()) !=0) {
+      if (dolink)
+         fXML->AddChild(topnode, key->KeyNode());
+      else 
+         fXML->UnlinkNode(key->KeyNode());   
+      if (key->IsSubdir()) 
+         CombineNodesTree(FindKeyDir(dir, key->GetKeyId()), key->KeyNode(), dolink);
+   }
+}
+
+
 //______________________________________________________________________________
 Bool_t TXMLFile::ReadFromFile()
 {
@@ -602,6 +633,9 @@ Bool_t TXMLFile::ReadFromFile()
          return kFALSE;
       }
 
+   ReadKeysList(this, fRootNode);
+
+/*
    XMLNodePointer_t keynode = fXML->GetChild(fRootNode);
    fXML->SkipEmpty(keynode);
    while (keynode!=0) {
@@ -610,7 +644,7 @@ Bool_t TXMLFile::ReadFromFile()
       if (strcmp(xmlio::Xmlkey, fXML->GetNodeName(keynode))==0) {
          fXML->UnlinkNode(keynode);
 
-         TKeyXML* key = new TKeyXML(this, keynode);
+         TKeyXML* key = new TKeyXML(this, ++fKeyCounter, keynode);
          AppendKey(key);
 
          if (gDebug>2)
@@ -620,12 +654,46 @@ Bool_t TXMLFile::ReadFromFile()
       keynode = next;
       fXML->SkipEmpty(keynode);
    }
+*/
 
    fXML->CleanNode(fRootNode);
    
    return kTRUE;
 }
 
+//______________________________________________________________________________
+Int_t TXMLFile::ReadKeysList(TDirectory* dir, XMLNodePointer_t topnode)
+{
+   // Read list of keys for directory
+   
+   if ((dir==0) || (topnode==0)) return 0;
+   
+   Int_t nkeys = 0;
+   
+   XMLNodePointer_t keynode = fXML->GetChild(topnode);
+   fXML->SkipEmpty(keynode);
+   while (keynode!=0) {
+      XMLNodePointer_t next = fXML->GetNext(keynode);
+
+      if (strcmp(xmlio::Xmlkey, fXML->GetNodeName(keynode))==0) {
+         fXML->UnlinkNode(keynode);
+
+         TKeyXML* key = new TKeyXML(dir, ++fKeyCounter, keynode);
+         dir->AppendKey(key);
+
+         if (gDebug>2)
+            Info("ReadKeysList","Add key %s from node %s",key->GetName(), fXML->GetNodeName(keynode));
+            
+         nkeys++;
+      }
+
+      keynode = next;
+      fXML->SkipEmpty(keynode);
+   }
+   
+   return nkeys;
+}
+
 //______________________________________________________________________________
 void TXMLFile::WriteStreamerInfo()
 {
@@ -917,3 +985,92 @@ void TXMLFile::SetUseNamespaces(Bool_t iUseNamespaces)
    if (IsWritable() && (GetListOfKeys()->GetSize()==0))
       TXMLSetup::SetUseNamespaces(iUseNamespaces);
 }
+
+//______________________________________________________________________________
+Long64_t TXMLFile::DirCreateEntry(TDirectory* dir)
+{
+   // Create key for directory entry in the key
+
+   TDirectory* mother = dir->GetMotherDir();
+   if (mother==0) mother = this;
+
+   TKeyXML* key = new TKeyXML(mother, ++fKeyCounter, dir, dir->GetName(), dir->GetTitle());
+   
+   key->SetSubir();
+   
+   return key->GetKeyId();
+}
+
+//______________________________________________________________________________
+TKeyXML* TXMLFile::FindDirKey(TDirectory* dir)
+{
+   // Serach for key which correspond to direcory dir
+   
+   TDirectory* motherdir = dir->GetMotherDir();
+   if (motherdir==0) motherdir = this;
+
+   TIter next(motherdir->GetListOfKeys());
+   TObject* obj = 0;
+   
+   while ((obj = next())!=0) {
+      TKeyXML* key = dynamic_cast<TKeyXML*> (obj);
+      
+      if (key!=0)
+         if (key->GetKeyId()==dir->GetSeekDir()) return key;
+   }
+   
+   return 0;
+}
+
+
+//______________________________________________________________________________
+TDirectory* TXMLFile::FindKeyDir(TDirectory* motherdir, Long64_t keyid)
+{
+   if (motherdir==0) motherdir = this;
+   
+   TIter next(motherdir->GetList());
+   TObject* obj = 0;
+   
+   while ((obj = next())!=0) {
+      TDirectory* dir = dynamic_cast<TDirectory*> (obj);
+      if (dir!=0)
+         if (dir->GetSeekDir()==keyid) return dir;
+   }
+   
+   return 0;
+   
+}
+
+//______________________________________________________________________________
+Int_t TXMLFile::DirReadKeys(TDirectory* dir)
+{
+   // Read keys for directory
+   // Make sence only once, while next time no new subnodes will be created
+   
+   TKeyXML* key = FindDirKey(dir);
+   if (key==0) return 0;
+   
+   return ReadKeysList(dir, key->KeyNode());
+}
+
+//______________________________________________________________________________
+void TXMLFile::DirWriteKeys(TDirectory*)
+{
+   // Update key attributes
+
+   TIter next(GetListOfKeys());
+   TObject* obj = 0;
+   
+   while ((obj = next())!=0) {
+      TKeyXML* key = dynamic_cast<TKeyXML*> (obj);
+      if (key!=0) key->UpdateAttributes();
+   }
+}
+
+//______________________________________________________________________________
+void TXMLFile::DirWriteHeader(TDirectory* dir)
+{
+   TKeyXML* key = FindDirKey(dir);
+   if (key!=0)
+      key->UpdateObject(dir);
+}