// @(#)root/sql:$Name:  $:$Id: TKeySQL.cxx,v 1.5 2005/12/07 14:59:57 rdm Exp $
// Author: Sergey Linev  20/11/2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//________________________________________________________________________
//
// TKeySQL is represents a metainforamtion about object, which was written to
// SQL database. It keeps object id, which used to locate object data
// from database tables.
//________________________________________________________________________


#include "TKeySQL.h"

#include "TClass.h"
#include "TBrowser.h"
#include "Riostream.h"

#include "TSQLResult.h"
#include "TBufferSQL2.h"
#include "TSQLStructure.h"
#include "TSQLFile.h"

ClassImp(TKeySQL);

//______________________________________________________________________________
 TKeySQL::TKeySQL() :
   TKey(),
   fFile(0),
   fKeyId(-1)
{
   // default constructor
}

//______________________________________________________________________________
 TKeySQL::TKeySQL(TSQLFile* file, const TObject* obj, const char* name) :
    TKey(),
    fFile(file),
    fKeyId(-1),
    fObjId(-1)
{
   // Creates TKeySQL and convert obj data to TSQLStructure via TBufferSQL2

   if (name) SetName(name); else
      if (obj!=0) {SetName(obj->GetName());  fClassName=obj->ClassName();}
      else SetName("Noname");

   StoreObject((void*)obj, obj ? obj->IsA() : 0);
}

//______________________________________________________________________________
 TKeySQL::TKeySQL(TSQLFile* file, const void* obj, const TClass* cl, const char* name) :
    TKey(),
    fFile(file),
    fKeyId(-1),
    fObjId(-1)
{
   // Creates TKeySQL and convert obj data to TSQLStructure via TBufferSQL2

   if (name && *name) SetName(name);
   else SetName(cl ? cl->GetName() : "Noname");

   StoreObject(obj, cl);
}

//______________________________________________________________________________
 TKeySQL::TKeySQL(TSQLFile* file, Int_t keyid, Int_t dirid, Int_t objid, const char* name,
                 const char* keydatetime, Int_t cycle, const char* classname) :
    TKey(),
    fFile(file),
    fKeyId(keyid),
    fDirId(dirid),
    fObjId(objid)
{
   // Create TKeySQL object, which correponds to single entry in keys table

   SetName(name);
   TDatime dt(keydatetime);
   fDatime = dt;
   fCycle = cycle;
   fClassName = classname;
}

//______________________________________________________________________________
 TKeySQL::~TKeySQL()
{
// TKeySQL destructor
}

//______________________________________________________________________________
 void TKeySQL::Browse(TBrowser *b)
{
// Browse object corresponding to this key

   TObject *obj = gDirectory->GetList()->FindObject(GetName());
   if (obj && !obj->IsFolder()) {
      if (obj->InheritsFrom(TCollection::Class()))
         obj->Delete();   // delete also collection elements
      delete obj;
      obj = 0;
   }

   if (!obj)
      obj = ReadObj();

   if (b && obj) {
      obj->Browse(b);
      b->SetRefreshFlag(kTRUE);
   }
}

//______________________________________________________________________________
 void TKeySQL::Delete(Option_t * /*option*/)
{
// Removes key from current directory
// Note: TKeySQL object is not deleted. You still have to call "delete key"

   if (fFile!=0)
      fFile->DeleteKeyFromDB(GetDBKeyId());

   gDirectory->GetListOfKeys()->Remove(this);
}

//______________________________________________________________________________
 void TKeySQL::StoreObject(const void* obj, const TClass* cl)
{
//  convert object to sql statements and store them in DB

   TObjArray cmds;
   Bool_t needcommit = kFALSE;

   fCycle = fFile->AppendKey(this);

   fKeyId = fFile->DefineNextKeyId();

   fObjId = fFile->VerifyObjectTable();
   if (fObjId<=0) fObjId = 1;
   else fObjId++;

   TBufferSQL2 buffer(TBuffer::kWrite, fFile);

   TSQLStructure* s = buffer.SqlWrite(obj, cl, fObjId);

   if ((buffer.GetErrorFlag()>0) || (s==0)) {
      Error("StoreObject","Cannot convert object data to TSQLStructure");
      goto zombie;
   }

   if (cl) fClassName = cl->GetName();
   
   if (fFile->GetUseTransactions()==TSQLFile::kTransactionsAuto) {
      fFile->SQLStartTransaction();
      needcommit = kTRUE;
   }

   // here tables may be already created, therefore 
   // it should be protected by transactions operations
   if (!s->ConvertToTables(fFile, fKeyId, &cmds)) {
      Error("StoreObject","Cannot convert to SQL statements");
      goto zombie;
   }
   
   if (!fFile->SQLApplyCommands(&cmds)) {
      Error("StoreObject","Cannot correctly store object data in database");
      goto zombie; 
   }

   // commit here, while objects data is already stored 
   if (needcommit) {
      fFile->SQLCommit();
      needcommit = kFALSE;
   }

   cmds.Delete();

   fDatime.Set();
   
   if (!fFile->WriteKeyData(GetDBKeyId(),
                            sqlio::Ids_RootDir, // later parent directory id should be
                            GetDBObjId(),
                            GetName(),
                            GetDatime().AsSQLString(),
                            GetCycle(),
                            GetClassName())) {
      // cannot add entry to keys table                          
      Error("StoreObject","Cannot write data to key tables");
      // delete everything relevant for that key
      fFile->DeleteKeyFromDB(GetDBKeyId());
      goto zombie;                           
   }

   return;
   
zombie:
   if (needcommit)
      fFile->SQLRollback();

   cmds.Delete();
   gDirectory->GetListOfKeys()->Remove(this);
   // fix me !!! One should delete object by other means
   // delete this;
}

//______________________________________________________________________________
 TObject* TKeySQL::ReadObj()
{
// Read object derived from TObject class
// If it is not TObject or in case of error, return 0

   if (gDebug>0)
      cout << "TKeySQL::ReadObj fKeyId = " << fKeyId << endl;

   if ((fKeyId<=0) || (fFile==0)) return 0;

   TBufferSQL2 buffer(TBuffer::kRead, fFile);

   TObject* obj = buffer.SqlRead(fObjId);

   return obj;
}

//______________________________________________________________________________
 void* TKeySQL::ReadObjectAny(const TClass* /*cl*/)
{
// read object of any type from SQL database

   if ((fKeyId<=0) || (fFile==0)) return 0;

   TBufferSQL2 buffer(TBuffer::kRead, fFile);

   void* obj = buffer.SqlReadAny(fObjId, 0);

   return obj;
}



ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.